Coverage Report

Created: 2024-09-06 07:53

/src/libxml2/xmlIO.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * xmlIO.c : implementation of the I/O interfaces used by the parser
3
 *
4
 * See Copyright for the status of this software.
5
 *
6
 * daniel@veillard.com
7
 */
8
9
#define IN_LIBXML
10
#include "libxml.h"
11
12
#include <string.h>
13
#include <stdlib.h>
14
#include <errno.h>
15
16
#include <fcntl.h>
17
#include <sys/stat.h>
18
19
#if defined(_WIN32)
20
  #define WIN32_LEAN_AND_MEAN
21
  #include <windows.h>
22
  #include <io.h>
23
  #include <direct.h>
24
#else
25
  #include <unistd.h>
26
#endif
27
28
#ifdef LIBXML_ZLIB_ENABLED
29
#include <zlib.h>
30
#endif
31
#ifdef LIBXML_LZMA_ENABLED
32
#include <lzma.h>
33
#endif
34
35
#include <libxml/xmlIO.h>
36
#include <libxml/xmlmemory.h>
37
#include <libxml/uri.h>
38
#include <libxml/nanohttp.h>
39
#include <libxml/parserInternals.h>
40
#include <libxml/xmlerror.h>
41
#ifdef LIBXML_CATALOG_ENABLED
42
#include <libxml/catalog.h>
43
#endif
44
45
#include "private/buf.h"
46
#include "private/enc.h"
47
#include "private/entities.h"
48
#include "private/error.h"
49
#include "private/io.h"
50
51
#ifndef SIZE_MAX
52
254k
  #define SIZE_MAX ((size_t) -1)
53
#endif
54
55
/* #define VERBOSE_FAILURE */
56
57
2.75M
#define MINLEN 4000
58
59
#ifndef STDOUT_FILENO
60
  #define STDOUT_FILENO 1
61
#endif
62
63
#ifndef S_ISDIR
64
#  ifdef _S_ISDIR
65
#    define S_ISDIR(x) _S_ISDIR(x)
66
#  elif defined(S_IFDIR)
67
#    ifdef S_IFMT
68
#      define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
69
#    elif defined(_S_IFMT)
70
#      define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
71
#    endif
72
#  endif
73
#endif
74
75
/*
76
 * Input I/O callback sets
77
 */
78
typedef struct _xmlInputCallback {
79
    xmlInputMatchCallback matchcallback;
80
    xmlInputOpenCallback opencallback;
81
    xmlInputReadCallback readcallback;
82
    xmlInputCloseCallback closecallback;
83
} xmlInputCallback;
84
85
/* This dummy function only marks default IO in the callback table */
86
static int
87
xmlIODefaultMatch(const char *filename);
88
89
0
#define MAX_INPUT_CALLBACK 10
90
91
static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
92
static int xmlInputCallbackNr;
93
94
#ifdef LIBXML_OUTPUT_ENABLED
95
/*
96
 * Output I/O callback sets
97
 */
98
typedef struct _xmlOutputCallback {
99
    xmlOutputMatchCallback matchcallback;
100
    xmlOutputOpenCallback opencallback;
101
    xmlOutputWriteCallback writecallback;
102
    xmlOutputCloseCallback closecallback;
103
} xmlOutputCallback;
104
105
0
#define MAX_OUTPUT_CALLBACK 10
106
107
static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
108
static int xmlOutputCallbackNr;
109
#endif /* LIBXML_OUTPUT_ENABLED */
110
111
/************************************************************************
112
 *                  *
113
 *      Error handling          *
114
 *                  *
115
 ************************************************************************/
116
117
/**
118
 * xmlIOErr:
119
 * @code:  the error number
120
 *
121
 * Convert errno to xmlParserErrors.
122
 *
123
 * Returns an xmlParserErrors code.
124
 */
125
static int
126
xmlIOErr(int err)
127
0
{
128
0
    int code;
129
130
0
    if (err == 0) code = XML_IO_UNKNOWN;
131
0
#ifdef EACCES
132
0
    else if (err == EACCES) code = XML_IO_EACCES;
133
0
#endif
134
0
#ifdef EAGAIN
135
0
    else if (err == EAGAIN) code = XML_IO_EAGAIN;
136
0
#endif
137
0
#ifdef EBADF
138
0
    else if (err == EBADF) code = XML_IO_EBADF;
139
0
#endif
140
0
#ifdef EBADMSG
141
0
    else if (err == EBADMSG) code = XML_IO_EBADMSG;
142
0
#endif
143
0
#ifdef EBUSY
144
0
    else if (err == EBUSY) code = XML_IO_EBUSY;
145
0
#endif
146
0
#ifdef ECANCELED
147
0
    else if (err == ECANCELED) code = XML_IO_ECANCELED;
148
0
#endif
149
0
#ifdef ECHILD
150
0
    else if (err == ECHILD) code = XML_IO_ECHILD;
151
0
#endif
152
0
#ifdef EDEADLK
153
0
    else if (err == EDEADLK) code = XML_IO_EDEADLK;
154
0
#endif
155
0
#ifdef EDOM
156
0
    else if (err == EDOM) code = XML_IO_EDOM;
157
0
#endif
158
0
#ifdef EEXIST
159
0
    else if (err == EEXIST) code = XML_IO_EEXIST;
160
0
#endif
161
0
#ifdef EFAULT
162
0
    else if (err == EFAULT) code = XML_IO_EFAULT;
163
0
#endif
164
0
#ifdef EFBIG
165
0
    else if (err == EFBIG) code = XML_IO_EFBIG;
166
0
#endif
167
0
#ifdef EINPROGRESS
168
0
    else if (err == EINPROGRESS) code = XML_IO_EINPROGRESS;
169
0
#endif
170
0
#ifdef EINTR
171
0
    else if (err == EINTR) code = XML_IO_EINTR;
172
0
#endif
173
0
#ifdef EINVAL
174
0
    else if (err == EINVAL) code = XML_IO_EINVAL;
175
0
#endif
176
0
#ifdef EIO
177
0
    else if (err == EIO) code = XML_IO_EIO;
178
0
#endif
179
0
#ifdef EISDIR
180
0
    else if (err == EISDIR) code = XML_IO_EISDIR;
181
0
#endif
182
0
#ifdef EMFILE
183
0
    else if (err == EMFILE) code = XML_IO_EMFILE;
184
0
#endif
185
0
#ifdef EMLINK
186
0
    else if (err == EMLINK) code = XML_IO_EMLINK;
187
0
#endif
188
0
#ifdef EMSGSIZE
189
0
    else if (err == EMSGSIZE) code = XML_IO_EMSGSIZE;
190
0
#endif
191
0
#ifdef ENAMETOOLONG
192
0
    else if (err == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
193
0
#endif
194
0
#ifdef ENFILE
195
0
    else if (err == ENFILE) code = XML_IO_ENFILE;
196
0
#endif
197
0
#ifdef ENODEV
198
0
    else if (err == ENODEV) code = XML_IO_ENODEV;
199
0
#endif
200
0
#ifdef ENOENT
201
0
    else if (err == ENOENT) code = XML_IO_ENOENT;
202
0
#endif
203
0
#ifdef ENOEXEC
204
0
    else if (err == ENOEXEC) code = XML_IO_ENOEXEC;
205
0
#endif
206
0
#ifdef ENOLCK
207
0
    else if (err == ENOLCK) code = XML_IO_ENOLCK;
208
0
#endif
209
0
#ifdef ENOMEM
210
0
    else if (err == ENOMEM) code = XML_IO_ENOMEM;
211
0
#endif
212
0
#ifdef ENOSPC
213
0
    else if (err == ENOSPC) code = XML_IO_ENOSPC;
214
0
#endif
215
0
#ifdef ENOSYS
216
0
    else if (err == ENOSYS) code = XML_IO_ENOSYS;
217
0
#endif
218
0
#ifdef ENOTDIR
219
0
    else if (err == ENOTDIR) code = XML_IO_ENOTDIR;
220
0
#endif
221
0
#ifdef ENOTEMPTY
222
0
    else if (err == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
223
0
#endif
224
0
#ifdef ENOTSUP
225
0
    else if (err == ENOTSUP) code = XML_IO_ENOTSUP;
226
0
#endif
227
0
#ifdef ENOTTY
228
0
    else if (err == ENOTTY) code = XML_IO_ENOTTY;
229
0
#endif
230
0
#ifdef ENXIO
231
0
    else if (err == ENXIO) code = XML_IO_ENXIO;
232
0
#endif
233
0
#ifdef EPERM
234
0
    else if (err == EPERM) code = XML_IO_EPERM;
235
0
#endif
236
0
#ifdef EPIPE
237
0
    else if (err == EPIPE) code = XML_IO_EPIPE;
238
0
#endif
239
0
#ifdef ERANGE
240
0
    else if (err == ERANGE) code = XML_IO_ERANGE;
241
0
#endif
242
0
#ifdef EROFS
243
0
    else if (err == EROFS) code = XML_IO_EROFS;
244
0
#endif
245
0
#ifdef ESPIPE
246
0
    else if (err == ESPIPE) code = XML_IO_ESPIPE;
247
0
#endif
248
0
#ifdef ESRCH
249
0
    else if (err == ESRCH) code = XML_IO_ESRCH;
250
0
#endif
251
0
#ifdef ETIMEDOUT
252
0
    else if (err == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
253
0
#endif
254
0
#ifdef EXDEV
255
0
    else if (err == EXDEV) code = XML_IO_EXDEV;
256
0
#endif
257
0
#ifdef ENOTSOCK
258
0
    else if (err == ENOTSOCK) code = XML_IO_ENOTSOCK;
259
0
#endif
260
0
#ifdef EISCONN
261
0
    else if (err == EISCONN) code = XML_IO_EISCONN;
262
0
#endif
263
0
#ifdef ECONNREFUSED
264
0
    else if (err == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
265
0
#endif
266
0
#ifdef ETIMEDOUT
267
0
    else if (err == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
268
0
#endif
269
0
#ifdef ENETUNREACH
270
0
    else if (err == ENETUNREACH) code = XML_IO_ENETUNREACH;
271
0
#endif
272
0
#ifdef EADDRINUSE
273
0
    else if (err == EADDRINUSE) code = XML_IO_EADDRINUSE;
274
0
#endif
275
0
#ifdef EINPROGRESS
276
0
    else if (err == EINPROGRESS) code = XML_IO_EINPROGRESS;
277
0
#endif
278
0
#ifdef EALREADY
279
0
    else if (err == EALREADY) code = XML_IO_EALREADY;
280
0
#endif
281
0
#ifdef EAFNOSUPPORT
282
0
    else if (err == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
283
0
#endif
284
0
    else code = XML_IO_UNKNOWN;
285
286
0
    return(code);
287
0
}
288
289
/************************************************************************
290
 *                  *
291
 *    Standard I/O for file accesses        *
292
 *                  *
293
 ************************************************************************/
294
295
#if defined(_WIN32)
296
297
/**
298
 * __xmlIOWin32UTF8ToWChar:
299
 * @u8String:  uft-8 string
300
 *
301
 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
302
 */
303
static wchar_t *
304
__xmlIOWin32UTF8ToWChar(const char *u8String)
305
{
306
    wchar_t *wString = NULL;
307
    int i;
308
309
    if (u8String) {
310
        int wLen =
311
            MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
312
                                -1, NULL, 0);
313
        if (wLen) {
314
            wString = xmlMalloc(wLen * sizeof(wchar_t));
315
            if (wString) {
316
                if (MultiByteToWideChar
317
                    (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
318
                    xmlFree(wString);
319
                    wString = NULL;
320
                }
321
            }
322
323
            /*
324
             * Convert to backward slash
325
             */
326
            for (i = 0; wString[i] != 0; i++) {
327
                if (wString[i] == '/')
328
                    wString[i] = '\\';
329
            }
330
        }
331
    }
332
333
    return wString;
334
}
335
336
#endif
337
338
/**
339
 * xmlNormalizeWindowsPath:
340
 * @path: the input file path
341
 *
342
 * DEPRECATED: This never really worked.
343
 *
344
 * Returns a copy of path.
345
 */
346
xmlChar *
347
xmlNormalizeWindowsPath(const xmlChar *path)
348
0
{
349
0
    return xmlStrdup(path);
350
0
}
351
352
/**
353
 * xmlCheckFilename:
354
 * @path:  the path to check
355
 *
356
 * DEPRECATED: Internal function, don't use.
357
 *
358
 * if stat is not available on the target machine,
359
 * returns 1.  if stat fails, returns 0 (if calling
360
 * stat on the filename fails, it can't be right).
361
 * if stat succeeds and the file is a directory,
362
 * returns 2.  otherwise returns 1.
363
 */
364
int
365
xmlCheckFilename(const char *path)
366
0
{
367
#if defined(_WIN32)
368
    struct _stat stat_buffer;
369
#else
370
0
    struct stat stat_buffer;
371
0
#endif
372
0
    int res;
373
374
0
    if (path == NULL)
375
0
  return(0);
376
377
#if defined(_WIN32)
378
    {
379
        wchar_t *wpath;
380
381
        /*
382
         * On Windows stat and wstat do not work with long pathname,
383
         * which start with '\\?\'
384
         */
385
        if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
386
            (path[3] == '\\') )
387
                return 1;
388
389
        wpath = __xmlIOWin32UTF8ToWChar(path);
390
        if (wpath == NULL)
391
            return(0);
392
        res = _wstat(wpath, &stat_buffer);
393
        xmlFree(wpath);
394
    }
395
#else
396
0
    res = stat(path, &stat_buffer);
397
0
#endif
398
399
0
    if (res < 0)
400
0
        return 0;
401
402
0
#ifdef S_ISDIR
403
0
    if (S_ISDIR(stat_buffer.st_mode))
404
0
        return 2;
405
0
#endif
406
407
0
    return 1;
408
0
}
409
410
static int
411
0
xmlConvertUriToPath(const char *uri, char **out) {
412
0
    const char *escaped;
413
0
    char *unescaped;
414
415
0
    *out = NULL;
416
417
0
    if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file://localhost/", 17)) {
418
0
  escaped = &uri[16];
419
0
    } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:///", 8)) {
420
0
  escaped = &uri[7];
421
0
    } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:/", 6)) {
422
        /* lots of generators seems to lazy to read RFC 1738 */
423
0
  escaped = &uri[5];
424
0
    } else {
425
0
        return(1);
426
0
    }
427
428
#ifdef _WIN32
429
    /* Ignore slash like in file:///C:/file.txt */
430
    escaped += 1;
431
#endif
432
433
0
    unescaped = xmlURIUnescapeString(escaped, 0, NULL);
434
0
    if (unescaped == NULL)
435
0
        return(-1);
436
437
0
    *out = unescaped;
438
0
    return(0);
439
0
}
440
441
/**
442
 * xmlFdOpen:
443
 * @filename:  the URI for matching
444
 * @out:  pointer to resulting context
445
 *
446
 * Returns an xmlParserErrors code
447
 */
448
static int
449
0
xmlFdOpen(const char *filename, int write, int *out) {
450
0
    char *fromUri = NULL;
451
0
    int flags;
452
0
    int fd;
453
0
    int ret;
454
455
0
    *out = -1;
456
0
    if (filename == NULL)
457
0
        return(XML_ERR_ARGUMENT);
458
459
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
460
0
        return(XML_ERR_NO_MEMORY);
461
462
0
    if (fromUri != NULL)
463
0
        filename = fromUri;
464
465
#if defined(_WIN32)
466
    {
467
        wchar_t *wpath;
468
469
        wpath = __xmlIOWin32UTF8ToWChar(filename);
470
        if (wpath == NULL) {
471
            xmlFree(fromUri);
472
            return(XML_ERR_NO_MEMORY);
473
        }
474
        if (write)
475
            flags = _O_WRONLY | _O_CREAT | _O_TRUNC;
476
        else
477
            flags = _O_RDONLY;
478
  fd = _wopen(wpath, flags | _O_BINARY, 0666);
479
        xmlFree(wpath);
480
    }
481
#else
482
0
    if (write)
483
0
        flags = O_WRONLY | O_CREAT | O_TRUNC;
484
0
    else
485
0
        flags = O_RDONLY;
486
0
    fd = open(filename, flags, 0666);
487
0
#endif /* WIN32 */
488
489
0
    if (fd < 0) {
490
        /*
491
         * Windows and possibly other platforms return EINVAL
492
         * for invalid filenames.
493
         */
494
0
        if ((errno == ENOENT) || (errno == EINVAL)) {
495
0
            ret = XML_IO_ENOENT;
496
0
        } else {
497
0
            ret = xmlIOErr(errno);
498
0
        }
499
0
    } else {
500
0
        *out = fd;
501
0
        ret = XML_ERR_OK;
502
0
    }
503
504
0
    xmlFree(fromUri);
505
0
    return(ret);
506
0
}
507
508
/**
509
 * xmlFdRead:
510
 * @context:  the I/O context
511
 * @buffer:  where to drop data
512
 * @len:  number of bytes to read
513
 *
514
 * Read @len bytes to @buffer from the I/O channel.
515
 *
516
 * Returns the number of bytes read
517
 */
518
static int
519
0
xmlFdRead(void *context, char *buffer, int len) {
520
0
    int fd = (int) (ptrdiff_t) context;
521
0
    int ret = 0;
522
0
    int bytes;
523
524
0
    while (len > 0) {
525
0
        bytes = read(fd, buffer, len);
526
0
        if (bytes < 0) {
527
            /*
528
             * If we already got some bytes, return them without
529
             * raising an error.
530
             */
531
0
            if (ret > 0)
532
0
                break;
533
0
            return(-xmlIOErr(errno));
534
0
        }
535
0
        if (bytes == 0)
536
0
            break;
537
0
        ret += bytes;
538
0
        buffer += bytes;
539
0
        len -= bytes;
540
0
    }
541
542
0
    return(ret);
543
0
}
544
545
#ifdef LIBXML_OUTPUT_ENABLED
546
/**
547
 * xmlFdWrite:
548
 * @context:  the I/O context
549
 * @buffer:  where to get data
550
 * @len:  number of bytes to write
551
 *
552
 * Write @len bytes from @buffer to the I/O channel.
553
 *
554
 * Returns the number of bytes written
555
 */
556
static int
557
0
xmlFdWrite(void *context, const char *buffer, int len) {
558
0
    int fd = (int) (ptrdiff_t) context;
559
0
    int ret = 0;
560
0
    int bytes;
561
562
0
    while (len > 0) {
563
0
  bytes = write(fd, buffer, len);
564
0
  if (bytes < 0)
565
0
            return(-xmlIOErr(errno));
566
0
        ret += bytes;
567
0
        buffer += bytes;
568
0
        len -= bytes;
569
0
    }
570
571
0
    return(ret);
572
0
}
573
#endif /* LIBXML_OUTPUT_ENABLED */
574
575
/**
576
 * xmlFdClose:
577
 * @context:  the I/O context
578
 *
579
 * Close an I/O channel
580
 *
581
 * Returns 0 in case of success and error code otherwise
582
 */
583
static int
584
0
xmlFdClose (void * context) {
585
0
    int ret;
586
587
0
    ret = close((int) (ptrdiff_t) context);
588
0
    if (ret < 0)
589
0
        return(xmlIOErr(errno));
590
591
0
    return(XML_ERR_OK);
592
0
}
593
594
/**
595
 * xmlFileMatch:
596
 * @filename:  the URI for matching
597
 *
598
 * DEPRECATED: Internal function, don't use.
599
 *
600
 * Returns 1 if matches, 0 otherwise
601
 */
602
int
603
0
xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
604
0
    return(1);
605
0
}
606
607
/**
608
 * xmlFileOpenSafe:
609
 * @filename:  the URI for matching
610
 * @out:  pointer to resulting context
611
 *
612
 * input from FILE *
613
 *
614
 * Returns an I/O context or NULL in case of error
615
 */
616
static int
617
0
xmlFileOpenSafe(const char *filename, int write, void **out) {
618
0
    char *fromUri = NULL;
619
0
    FILE *fd;
620
0
    int ret = XML_ERR_OK;
621
622
0
    *out = NULL;
623
0
    if (filename == NULL)
624
0
        return(XML_ERR_ARGUMENT);
625
626
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
627
0
        return(XML_ERR_NO_MEMORY);
628
629
0
    if (fromUri != NULL)
630
0
        filename = fromUri;
631
632
#if defined(_WIN32)
633
    {
634
        wchar_t *wpath;
635
636
        wpath = __xmlIOWin32UTF8ToWChar(filename);
637
        if (wpath == NULL) {
638
            xmlFree(fromUri);
639
            return(XML_ERR_NO_MEMORY);
640
        }
641
  fd = _wfopen(wpath, write ? L"wb" : L"rb");
642
        xmlFree(wpath);
643
    }
644
#else
645
0
    fd = fopen(filename, write ? "wb" : "rb");
646
0
#endif /* WIN32 */
647
648
0
    if (fd == NULL) {
649
        /*
650
         * Windows and possibly other platforms return EINVAL
651
         * for invalid filenames.
652
         */
653
0
        if ((errno == ENOENT) || (errno == EINVAL)) {
654
0
            ret = XML_IO_ENOENT;
655
0
        } else {
656
            /*
657
             * This error won't be forwarded to the parser context
658
             * which will report it a second time.
659
             */
660
0
            ret = xmlIOErr(errno);
661
0
        }
662
0
    }
663
664
0
    *out = fd;
665
0
    xmlFree(fromUri);
666
0
    return(ret);
667
0
}
668
669
/**
670
 * xmlFileOpen:
671
 * @filename:  the URI for matching
672
 *
673
 * DEPRECATED: Internal function, don't use.
674
 *
675
 * Returns an IO context or NULL in case or failure
676
 */
677
void *
678
0
xmlFileOpen(const char *filename) {
679
0
    void *context;
680
681
0
    xmlFileOpenSafe(filename, 0, &context);
682
0
    return(context);
683
0
}
684
685
/**
686
 * xmlFileRead:
687
 * @context:  the I/O context
688
 * @buffer:  where to drop data
689
 * @len:  number of bytes to write
690
 *
691
 * DEPRECATED: Internal function, don't use.
692
 *
693
 * Returns the number of bytes read or < 0 in case of failure
694
 */
695
int
696
0
xmlFileRead(void * context, char * buffer, int len) {
697
0
    FILE *file = context;
698
0
    size_t bytes;
699
700
0
    if ((context == NULL) || (buffer == NULL))
701
0
        return(-1);
702
703
    /*
704
     * The C standard doesn't mandate that fread sets errno, only
705
     * POSIX does. The Windows documentation isn't really clear.
706
     * Set errno to zero which will be reported as unknown error
707
     * if fread fails without setting errno.
708
     */
709
0
    errno = 0;
710
0
    bytes = fread(buffer, 1, len, file);
711
0
    if ((bytes < (size_t) len) && (ferror(file)))
712
0
        return(-xmlIOErr(errno));
713
714
0
    return(bytes);
715
0
}
716
717
#ifdef LIBXML_OUTPUT_ENABLED
718
/**
719
 * xmlFileWrite:
720
 * @context:  the I/O context
721
 * @buffer:  where to drop data
722
 * @len:  number of bytes to write
723
 *
724
 * Write @len bytes from @buffer to the I/O channel.
725
 *
726
 * Returns the number of bytes written
727
 */
728
static int
729
0
xmlFileWrite(void *context, const char *buffer, int len) {
730
0
    FILE *file = context;
731
0
    size_t bytes;
732
733
0
    if ((context == NULL) || (buffer == NULL))
734
0
        return(-1);
735
736
0
    errno = 0;
737
0
    bytes = fwrite(buffer, 1, len, file);
738
0
    if (bytes < (size_t) len)
739
0
        return(-xmlIOErr(errno));
740
741
0
    return(len);
742
0
}
743
#endif /* LIBXML_OUTPUT_ENABLED */
744
745
/**
746
 * xmlFileFlush:
747
 * @context:  the I/O context
748
 *
749
 * Flush an I/O channel
750
 */
751
static int
752
0
xmlFileFlush (void * context) {
753
0
    FILE *file = context;
754
755
0
    if (file == NULL)
756
0
        return(-1);
757
758
0
    if (fflush(file) != 0)
759
0
        return(xmlIOErr(errno));
760
761
0
    return(XML_ERR_OK);
762
0
}
763
764
/**
765
 * xmlFileClose:
766
 * @context:  the I/O context
767
 *
768
 * DEPRECATED: Internal function, don't use.
769
 *
770
 * Returns 0 or -1 an error code case of error
771
 */
772
int
773
0
xmlFileClose (void * context) {
774
0
    FILE *file = context;
775
776
0
    if (context == NULL)
777
0
        return(-1);
778
779
0
    if (file == stdin)
780
0
        return(0);
781
0
    if ((file == stdout) || (file == stderr))
782
0
        return(xmlFileFlush(file));
783
784
0
    if (fclose(file) != 0)
785
0
        return(xmlIOErr(errno));
786
787
0
    return(0);
788
0
}
789
790
#ifdef LIBXML_OUTPUT_ENABLED
791
/**
792
 * xmlBufferWrite:
793
 * @context:  the xmlBuffer
794
 * @buffer:  the data to write
795
 * @len:  number of bytes to write
796
 *
797
 * Write @len bytes from @buffer to the xml buffer
798
 *
799
 * Returns the number of bytes written or a negative xmlParserErrors
800
 * value.
801
 */
802
static int
803
0
xmlBufferWrite (void * context, const char * buffer, int len) {
804
0
    int ret;
805
806
0
    ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
807
0
    if (ret != 0)
808
0
        return(-XML_ERR_NO_MEMORY);
809
0
    return(len);
810
0
}
811
#endif
812
813
#ifdef LIBXML_ZLIB_ENABLED
814
/************************************************************************
815
 *                  *
816
 *    I/O for compressed file accesses      *
817
 *                  *
818
 ************************************************************************/
819
820
/**
821
 * xmlGzfileRead:
822
 * @context:  the I/O context
823
 * @buffer:  where to drop data
824
 * @len:  number of bytes to write
825
 *
826
 * Read @len bytes to @buffer from the compressed I/O channel.
827
 *
828
 * Returns the number of bytes read.
829
 */
830
static int
831
xmlGzfileRead (void * context, char * buffer, int len) {
832
    int ret;
833
834
    ret = gzread((gzFile) context, &buffer[0], len);
835
    if (ret < 0)
836
        return(-XML_IO_UNKNOWN);
837
    return(ret);
838
}
839
840
#ifdef LIBXML_OUTPUT_ENABLED
841
/**
842
 * xmlGzfileWrite:
843
 * @context:  the I/O context
844
 * @buffer:  where to drop data
845
 * @len:  number of bytes to write
846
 *
847
 * Write @len bytes from @buffer to the compressed I/O channel.
848
 *
849
 * Returns the number of bytes written
850
 */
851
static int
852
xmlGzfileWrite (void * context, const char * buffer, int len) {
853
    int ret;
854
855
    ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
856
    if (ret < 0)
857
        return(-XML_IO_UNKNOWN);
858
    return(ret);
859
}
860
#endif /* LIBXML_OUTPUT_ENABLED */
861
862
/**
863
 * xmlGzfileClose:
864
 * @context:  the I/O context
865
 *
866
 * Close a compressed I/O channel
867
 */
868
static int
869
xmlGzfileClose (void * context) {
870
    if (gzclose((gzFile) context) != Z_OK)
871
        return(XML_IO_UNKNOWN);
872
    return(0);
873
}
874
#endif /* LIBXML_ZLIB_ENABLED */
875
876
/************************************************************************
877
 *                  *
878
 *    I/O for compressed file accesses      *
879
 *                  *
880
 ************************************************************************/
881
882
#ifdef LIBXML_LZMA_ENABLED
883
884
#include "private/xzlib.h"
885
886
/**
887
 * xmlXzfileRead:
888
 * @context:  the I/O context
889
 * @buffer:  where to drop data
890
 * @len:  number of bytes to write
891
 *
892
 * Read @len bytes to @buffer from the compressed I/O channel.
893
 *
894
 * Returns the number of bytes written
895
 */
896
static int
897
xmlXzfileRead (void * context, char * buffer, int len) {
898
    int ret;
899
900
    ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
901
    if (ret < 0)
902
        return(-XML_IO_UNKNOWN);
903
    return(ret);
904
}
905
906
/**
907
 * xmlXzfileClose:
908
 * @context:  the I/O context
909
 *
910
 * Close a compressed I/O channel
911
 */
912
static int
913
xmlXzfileClose (void * context) {
914
    if (__libxml2_xzclose((xzFile) context) != LZMA_OK)
915
        return(XML_IO_UNKNOWN);
916
    return(0);
917
}
918
#endif /* LIBXML_LZMA_ENABLED */
919
920
/************************************************************************
921
 *                  *
922
 *      I/O for HTTP file accesses      *
923
 *                  *
924
 ************************************************************************/
925
926
#ifdef LIBXML_HTTP_ENABLED
927
/**
928
 * xmlIOHTTPMatch:
929
 * @filename:  the URI for matching
930
 *
931
 * DEPRECATED: Internal function, don't use.
932
 *
933
 * check if the URI matches an HTTP one
934
 *
935
 * Returns 1 if matches, 0 otherwise
936
 */
937
int
938
xmlIOHTTPMatch (const char *filename) {
939
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
940
  return(1);
941
    return(0);
942
}
943
944
/**
945
 * xmlIOHTTPOpen:
946
 * @filename:  the URI for matching
947
 *
948
 * DEPRECATED: Internal function, don't use.
949
 *
950
 * open an HTTP I/O channel
951
 *
952
 * Returns an I/O context or NULL in case of error
953
 */
954
void *
955
xmlIOHTTPOpen (const char *filename) {
956
    return(xmlNanoHTTPOpen(filename, NULL));
957
}
958
959
#ifdef LIBXML_OUTPUT_ENABLED
960
/**
961
 * xmlIOHTTPOpenW:
962
 * @post_uri:  The destination URI for the document
963
 * @compression:  The compression desired for the document.
964
 *
965
 * DEPRECATED: Support for HTTP POST has been removed.
966
 *
967
 * Returns NULL.
968
 */
969
void *
970
xmlIOHTTPOpenW(const char *post_uri ATTRIBUTE_UNUSED,
971
               int compression ATTRIBUTE_UNUSED)
972
{
973
    return(NULL);
974
}
975
#endif /* LIBXML_OUTPUT_ENABLED */
976
977
/**
978
 * xmlIOHTTPRead:
979
 * @context:  the I/O context
980
 * @buffer:  where to drop data
981
 * @len:  number of bytes to write
982
 *
983
 * DEPRECATED: Internal function, don't use.
984
 *
985
 * Read @len bytes to @buffer from the I/O channel.
986
 *
987
 * Returns the number of bytes written
988
 */
989
int
990
xmlIOHTTPRead(void * context, char * buffer, int len) {
991
    if ((buffer == NULL) || (len < 0)) return(-1);
992
    return(xmlNanoHTTPRead(context, &buffer[0], len));
993
}
994
995
/**
996
 * xmlIOHTTPClose:
997
 * @context:  the I/O context
998
 *
999
 * DEPRECATED: Internal function, don't use.
1000
 *
1001
 * Close an HTTP I/O channel
1002
 *
1003
 * Returns 0
1004
 */
1005
int
1006
xmlIOHTTPClose (void * context) {
1007
    xmlNanoHTTPClose(context);
1008
    return 0;
1009
}
1010
#endif /* LIBXML_HTTP_ENABLED */
1011
1012
/************************************************************************
1013
 *                  *
1014
 *      Input/output buffers        *
1015
 *                  *
1016
 ************************************************************************/
1017
1018
static int
1019
0
xmlIODefaultMatch(const char *filename ATTRIBUTE_UNUSED) {
1020
0
    return(1);
1021
0
}
1022
1023
/**
1024
 * xmlInputDefaultOpen:
1025
 * @buf:  input buffer to be filled
1026
 * @filename:  filename or URI
1027
 * @flags:  XML_INPUT flags
1028
 *
1029
 * Returns an xmlParserErrors code.
1030
 */
1031
static int
1032
xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename,
1033
0
                    int flags) {
1034
0
    int ret;
1035
0
    int fd;
1036
1037
    /* Avoid unused variable warning */
1038
0
    (void) flags;
1039
1040
#ifdef LIBXML_HTTP_ENABLED
1041
    if (xmlIOHTTPMatch(filename)) {
1042
        if ((flags & XML_INPUT_NETWORK) == 0)
1043
            return(XML_IO_NETWORK_ATTEMPT);
1044
1045
        buf->context = xmlIOHTTPOpen(filename);
1046
1047
        if (buf->context != NULL) {
1048
            buf->readcallback = xmlIOHTTPRead;
1049
            buf->closecallback = xmlIOHTTPClose;
1050
            return(XML_ERR_OK);
1051
        }
1052
    }
1053
#endif /* LIBXML_HTTP_ENABLED */
1054
1055
0
    if (!xmlFileMatch(filename))
1056
0
        return(XML_IO_ENOENT);
1057
1058
#ifdef LIBXML_LZMA_ENABLED
1059
    if (flags & XML_INPUT_UNZIP) {
1060
        xzFile xzStream;
1061
1062
        ret = xmlFdOpen(filename, 0, &fd);
1063
        if (ret != XML_ERR_OK)
1064
            return(ret);
1065
1066
        xzStream = __libxml2_xzdopen(filename, fd, "rb");
1067
1068
        if (xzStream == NULL) {
1069
            close(fd);
1070
        } else {
1071
            if (__libxml2_xzcompressed(xzStream) > 0) {
1072
                buf->context = xzStream;
1073
                buf->readcallback = xmlXzfileRead;
1074
                buf->closecallback = xmlXzfileClose;
1075
                buf->compressed = 1;
1076
1077
                return(XML_ERR_OK);
1078
            }
1079
1080
            xmlXzfileClose(xzStream);
1081
        }
1082
    }
1083
#endif /* LIBXML_LZMA_ENABLED */
1084
1085
#ifdef LIBXML_ZLIB_ENABLED
1086
    if (flags & XML_INPUT_UNZIP) {
1087
        gzFile gzStream;
1088
1089
        ret = xmlFdOpen(filename, 0, &fd);
1090
        if (ret != XML_ERR_OK)
1091
            return(ret);
1092
1093
        gzStream = gzdopen(fd, "rb");
1094
1095
        if (gzStream == NULL) {
1096
            close(fd);
1097
        } else {
1098
            char buff4[4];
1099
1100
            if ((gzread(gzStream, buff4, 4) > 0) &&
1101
                (gzdirect(gzStream) == 0)) {
1102
                gzrewind(gzStream);
1103
1104
                buf->context = gzStream;
1105
                buf->readcallback = xmlGzfileRead;
1106
                buf->closecallback = xmlGzfileClose;
1107
                buf->compressed = 1;
1108
1109
                return(XML_ERR_OK);
1110
            }
1111
1112
            xmlGzfileClose(gzStream);
1113
        }
1114
    }
1115
#endif /* LIBXML_ZLIB_ENABLED */
1116
1117
0
    ret = xmlFdOpen(filename, 0, &fd);
1118
0
    if (ret != XML_ERR_OK)
1119
0
        return(ret);
1120
1121
0
    buf->context = (void *) (ptrdiff_t) fd;
1122
0
    buf->readcallback = xmlFdRead;
1123
0
    buf->closecallback = xmlFdClose;
1124
0
    return(XML_ERR_OK);
1125
0
}
1126
1127
#ifdef LIBXML_OUTPUT_ENABLED
1128
/**
1129
 * xmlOutputDefaultOpen:
1130
 * @buf:  input buffer to be filled
1131
 * @filename:  filename or URI
1132
 * @compression:  compression level or 0
1133
 * @is_file_uri:  whether filename is a file URI
1134
 *
1135
 * Returns an xmlParserErrors code.
1136
 */
1137
static int
1138
xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename,
1139
0
                     int compression) {
1140
0
    int fd;
1141
1142
0
    (void) compression;
1143
1144
0
    if (!strcmp(filename, "-")) {
1145
0
        fd = dup(STDOUT_FILENO);
1146
1147
0
        if (fd < 0)
1148
0
            return(xmlIOErr(errno));
1149
0
    } else {
1150
0
        int ret;
1151
1152
0
        ret = xmlFdOpen(filename, /* write */ 1, &fd);
1153
0
        if (ret != XML_ERR_OK)
1154
0
            return(ret);
1155
0
    }
1156
1157
#ifdef LIBXML_ZLIB_ENABLED
1158
    if ((compression > 0) && (compression <= 9)) {
1159
        gzFile gzStream;
1160
        char mode[15];
1161
1162
        snprintf(mode, sizeof(mode), "wb%d", compression);
1163
        gzStream = gzdopen(fd, mode);
1164
1165
        if (gzStream == NULL) {
1166
            close(fd);
1167
            return(XML_IO_UNKNOWN);
1168
        }
1169
1170
        buf->context = gzStream;
1171
        buf->writecallback = xmlGzfileWrite;
1172
        buf->closecallback = xmlGzfileClose;
1173
1174
        return(XML_ERR_OK);
1175
    }
1176
#endif /* LIBXML_ZLIB_ENABLED */
1177
1178
0
    buf->context = (void *) (ptrdiff_t) fd;
1179
0
    buf->writecallback = xmlFdWrite;
1180
0
    buf->closecallback = xmlFdClose;
1181
0
    return(XML_ERR_OK);
1182
0
}
1183
#endif
1184
1185
/**
1186
 * xmlAllocParserInputBuffer:
1187
 * @enc:  the charset encoding if known (deprecated)
1188
 *
1189
 * DEPRECATED: Use xmlNewInputFrom*.
1190
 *
1191
 * Create a buffered parser input for progressive parsing.
1192
 *
1193
 * The encoding argument is deprecated and should be set to
1194
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1195
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1196
 *
1197
 * Returns the new parser input or NULL
1198
 */
1199
xmlParserInputBufferPtr
1200
20.2k
xmlAllocParserInputBuffer(xmlCharEncoding enc) {
1201
20.2k
    xmlParserInputBufferPtr ret;
1202
1203
20.2k
    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1204
20.2k
    if (ret == NULL) {
1205
0
  return(NULL);
1206
0
    }
1207
20.2k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
1208
20.2k
    ret->buffer = xmlBufCreate(XML_IO_BUFFER_SIZE);
1209
20.2k
    if (ret->buffer == NULL) {
1210
0
        xmlFree(ret);
1211
0
  return(NULL);
1212
0
    }
1213
20.2k
    if (enc != XML_CHAR_ENCODING_NONE) {
1214
0
        if (xmlLookupCharEncodingHandler(enc, &ret->encoder) != 0) {
1215
            /* We can't handle errors properly here. */
1216
0
            xmlFreeParserInputBuffer(ret);
1217
0
            return(NULL);
1218
0
        }
1219
0
    }
1220
20.2k
    if (ret->encoder != NULL)
1221
0
        ret->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
1222
20.2k
    else
1223
20.2k
        ret->raw = NULL;
1224
20.2k
    ret->readcallback = NULL;
1225
20.2k
    ret->closecallback = NULL;
1226
20.2k
    ret->context = NULL;
1227
20.2k
    ret->compressed = -1;
1228
20.2k
    ret->rawconsumed = 0;
1229
1230
20.2k
    return(ret);
1231
20.2k
}
1232
1233
#ifdef LIBXML_OUTPUT_ENABLED
1234
/**
1235
 * xmlAllocOutputBuffer:
1236
 * @encoder:  the encoding converter or NULL
1237
 *
1238
 * Create a buffered parser output
1239
 *
1240
 * Consumes @encoder even in error case.
1241
 *
1242
 * Returns the new parser output or NULL
1243
 */
1244
xmlOutputBufferPtr
1245
0
xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
1246
0
    xmlOutputBufferPtr ret;
1247
1248
0
    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
1249
0
    if (ret == NULL) {
1250
0
        xmlCharEncCloseFunc(encoder);
1251
0
  return(NULL);
1252
0
    }
1253
0
    memset(ret, 0, sizeof(xmlOutputBuffer));
1254
0
    ret->buffer = xmlBufCreate(MINLEN);
1255
0
    if (ret->buffer == NULL) {
1256
0
        xmlCharEncCloseFunc(encoder);
1257
0
        xmlFree(ret);
1258
0
  return(NULL);
1259
0
    }
1260
1261
0
    ret->encoder = encoder;
1262
0
    if (encoder != NULL) {
1263
0
        ret->conv = xmlBufCreate(MINLEN);
1264
0
  if (ret->conv == NULL) {
1265
0
            xmlOutputBufferClose(ret);
1266
0
      return(NULL);
1267
0
  }
1268
1269
  /*
1270
   * This call is designed to initiate the encoder state
1271
   */
1272
0
  xmlCharEncOutput(ret, 1);
1273
0
    } else
1274
0
        ret->conv = NULL;
1275
0
    ret->writecallback = NULL;
1276
0
    ret->closecallback = NULL;
1277
0
    ret->context = NULL;
1278
0
    ret->written = 0;
1279
1280
0
    return(ret);
1281
0
}
1282
#endif /* LIBXML_OUTPUT_ENABLED */
1283
1284
/**
1285
 * xmlFreeParserInputBuffer:
1286
 * @in:  a buffered parser input
1287
 *
1288
 * Free up the memory used by a buffered parser input
1289
 */
1290
void
1291
38.7k
xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1292
38.7k
    if (in == NULL) return;
1293
1294
38.7k
    if (in->raw) {
1295
3.08k
        xmlBufFree(in->raw);
1296
3.08k
  in->raw = NULL;
1297
3.08k
    }
1298
38.7k
    if (in->encoder != NULL) {
1299
3.08k
        xmlCharEncCloseFunc(in->encoder);
1300
3.08k
    }
1301
38.7k
    if (in->closecallback != NULL) {
1302
20.2k
  in->closecallback(in->context);
1303
20.2k
    }
1304
38.7k
    if (in->buffer != NULL) {
1305
38.7k
        xmlBufFree(in->buffer);
1306
38.7k
  in->buffer = NULL;
1307
38.7k
    }
1308
1309
38.7k
    xmlFree(in);
1310
38.7k
}
1311
1312
#ifdef LIBXML_OUTPUT_ENABLED
1313
/**
1314
 * xmlOutputBufferClose:
1315
 * @out:  a buffered output
1316
 *
1317
 * flushes and close the output I/O channel
1318
 * and free up all the associated resources
1319
 *
1320
 * Returns the number of byte written or a negative xmlParserErrors
1321
 * code in case of error.
1322
 */
1323
int
1324
xmlOutputBufferClose(xmlOutputBufferPtr out)
1325
0
{
1326
0
    int ret;
1327
1328
0
    if (out == NULL)
1329
0
        return (-1);
1330
1331
0
    if (out->writecallback != NULL)
1332
0
        xmlOutputBufferFlush(out);
1333
1334
0
    if (out->closecallback != NULL) {
1335
0
        int code = out->closecallback(out->context);
1336
1337
0
        if ((code != XML_ERR_OK) && (out->error == XML_ERR_OK)) {
1338
0
            if (code < 0)
1339
0
                out->error = XML_IO_UNKNOWN;
1340
0
            else
1341
0
                out->error = code;
1342
0
        }
1343
0
    }
1344
1345
0
    if (out->error != XML_ERR_OK)
1346
0
        ret = -out->error;
1347
0
    else
1348
0
        ret = out->written;
1349
1350
0
    if (out->conv) {
1351
0
        xmlBufFree(out->conv);
1352
0
        out->conv = NULL;
1353
0
    }
1354
0
    if (out->encoder != NULL) {
1355
0
        xmlCharEncCloseFunc(out->encoder);
1356
0
    }
1357
0
    if (out->buffer != NULL) {
1358
0
        xmlBufFree(out->buffer);
1359
0
        out->buffer = NULL;
1360
0
    }
1361
1362
0
    xmlFree(out);
1363
1364
0
    return(ret);
1365
0
}
1366
#endif /* LIBXML_OUTPUT_ENABLED */
1367
1368
/**
1369
 * xmlParserInputBufferCreateUrl:
1370
 * @URI:  the filename or URI
1371
 * @enc:  encoding enum (deprecated)
1372
 * @flags:  XML_INPUT flags
1373
 * @out:  pointer to resulting input buffer
1374
 *
1375
 * Returns an xmlParserErrors code.
1376
 */
1377
int
1378
xmlParserInputBufferCreateUrl(const char *URI, xmlCharEncoding enc,
1379
0
                              int flags, xmlParserInputBufferPtr *out) {
1380
0
    xmlParserInputBufferPtr buf;
1381
0
    int ret;
1382
0
    int i;
1383
1384
0
    xmlInitParser();
1385
1386
0
    *out = NULL;
1387
0
    if (URI == NULL)
1388
0
        return(XML_ERR_ARGUMENT);
1389
1390
    /*
1391
     * Allocate the Input buffer front-end.
1392
     */
1393
0
    buf = xmlAllocParserInputBuffer(enc);
1394
0
    if (buf == NULL)
1395
0
        return(XML_ERR_NO_MEMORY);
1396
1397
    /*
1398
     * Try to find one of the input accept method accepting that scheme
1399
     * Go in reverse to give precedence to user defined handlers.
1400
     */
1401
0
    ret = XML_IO_ENOENT;
1402
0
    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
1403
0
        xmlInputCallback *cb = &xmlInputCallbackTable[i];
1404
1405
0
        if (cb->matchcallback == xmlIODefaultMatch) {
1406
0
            ret = xmlInputDefaultOpen(buf, URI, flags);
1407
1408
0
            if ((ret == XML_ERR_OK) || (ret != XML_IO_ENOENT))
1409
0
                break;
1410
0
        } else if ((cb->matchcallback != NULL) &&
1411
0
                   (cb->matchcallback(URI) != 0)) {
1412
0
            buf->context = cb->opencallback(URI);
1413
0
            if (buf->context != NULL) {
1414
0
                buf->readcallback = cb->readcallback;
1415
0
                buf->closecallback = cb->closecallback;
1416
0
                ret = XML_ERR_OK;
1417
0
                break;
1418
0
            }
1419
0
        }
1420
0
    }
1421
0
    if (ret != XML_ERR_OK) {
1422
0
        xmlFreeParserInputBuffer(buf);
1423
0
        *out = NULL;
1424
0
  return(ret);
1425
0
    }
1426
1427
0
    *out = buf;
1428
0
    return(ret);
1429
0
}
1430
1431
xmlParserInputBufferPtr
1432
0
__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1433
0
    xmlParserInputBufferPtr ret;
1434
1435
0
    xmlParserInputBufferCreateUrl(URI, enc, 0, &ret);
1436
0
    return(ret);
1437
0
}
1438
1439
/**
1440
 * xmlParserInputBufferCreateFilename:
1441
 * @URI:  a C string containing the URI or filename
1442
 * @enc:  the charset encoding if known
1443
 *
1444
 * DEPRECATED: Use xmlNewInputFromUrl.
1445
 *
1446
 * Create a buffered parser input for the progressive parsing of a file
1447
 * Automatic support for ZLIB/Compress compressed document is provided
1448
 * by default if found at compile-time.
1449
 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1450
 *
1451
 * Returns the new parser input or NULL
1452
 */
1453
xmlParserInputBufferPtr
1454
0
xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1455
0
    xmlParserInputBufferPtr ret;
1456
1457
0
    if (xmlParserInputBufferCreateFilenameValue != NULL)
1458
0
        return(xmlParserInputBufferCreateFilenameValue(URI, enc));
1459
1460
0
    xmlParserInputBufferCreateUrl(URI, enc, 0, &ret);
1461
0
    return(ret);
1462
0
}
1463
1464
#ifdef LIBXML_OUTPUT_ENABLED
1465
xmlOutputBufferPtr
1466
__xmlOutputBufferCreateFilename(const char *URI,
1467
                              xmlCharEncodingHandlerPtr encoder,
1468
0
                              int compression) {
1469
0
    xmlOutputBufferPtr ret;
1470
0
    xmlURIPtr puri;
1471
0
    int i = 0;
1472
0
    char *unescaped = NULL;
1473
1474
0
    xmlInitParser();
1475
1476
0
    if (URI == NULL)
1477
0
        return(NULL);
1478
1479
0
    puri = xmlParseURI(URI);
1480
0
    if (puri != NULL) {
1481
        /*
1482
         * try to limit the damages of the URI unescaping code.
1483
         */
1484
0
        if (puri->scheme == NULL) {
1485
0
            unescaped = xmlURIUnescapeString(URI, 0, NULL);
1486
0
            if (unescaped == NULL) {
1487
0
                xmlFreeURI(puri);
1488
0
                xmlCharEncCloseFunc(encoder);
1489
0
                return(NULL);
1490
0
            }
1491
0
            URI = unescaped;
1492
0
        }
1493
0
        xmlFreeURI(puri);
1494
0
    }
1495
1496
    /*
1497
     * Allocate the Output buffer front-end.
1498
     */
1499
0
    ret = xmlAllocOutputBuffer(encoder);
1500
0
    if (ret == NULL) {
1501
0
        xmlFree(unescaped);
1502
0
        return(NULL);
1503
0
    }
1504
1505
    /*
1506
     * Try to find one of the output accept method accepting that scheme
1507
     * Go in reverse to give precedence to user defined handlers.
1508
     */
1509
0
    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
1510
0
        xmlOutputCallback *cb = &xmlOutputCallbackTable[i];
1511
0
        int code;
1512
1513
0
        if (cb->matchcallback == xmlIODefaultMatch) {
1514
0
            code = xmlOutputDefaultOpen(ret, URI, compression);
1515
            /* TODO: Handle other errors */
1516
0
            if (code == XML_ERR_OK)
1517
0
                break;
1518
0
        } else if ((cb->matchcallback != NULL) &&
1519
0
                   (cb->matchcallback(URI) != 0)) {
1520
0
            ret->context = cb->opencallback(URI);
1521
0
            if (ret->context != NULL) {
1522
0
                ret->writecallback = cb->writecallback;
1523
0
                ret->closecallback = cb->closecallback;
1524
0
                break;
1525
0
            }
1526
0
        }
1527
0
    }
1528
1529
0
    if (ret->context == NULL) {
1530
0
        xmlOutputBufferClose(ret);
1531
0
  ret = NULL;
1532
0
    }
1533
1534
0
    xmlFree(unescaped);
1535
0
    return(ret);
1536
0
}
1537
1538
/**
1539
 * xmlOutputBufferCreateFilename:
1540
 * @URI:  a C string containing the URI or filename
1541
 * @encoder:  the encoding converter or NULL
1542
 * @compression:  the compression ration (0 none, 9 max).
1543
 *
1544
 * Create a buffered  output for the progressive saving of a file
1545
 * If filename is "-' then we use stdout as the output.
1546
 * Automatic support for ZLIB/Compress compressed document is provided
1547
 * by default if found at compile-time.
1548
 * TODO: currently if compression is set, the library only support
1549
 *       writing to a local file.
1550
 *
1551
 * Consumes @encoder even in error case.
1552
 *
1553
 * Returns the new output or NULL
1554
 */
1555
xmlOutputBufferPtr
1556
xmlOutputBufferCreateFilename(const char *URI,
1557
                              xmlCharEncodingHandlerPtr encoder,
1558
0
                              int compression ATTRIBUTE_UNUSED) {
1559
0
    if ((xmlOutputBufferCreateFilenameValue)) {
1560
0
    return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
1561
0
  }
1562
0
  return __xmlOutputBufferCreateFilename(URI, encoder, compression);
1563
0
}
1564
#endif /* LIBXML_OUTPUT_ENABLED */
1565
1566
/**
1567
 * xmlParserInputBufferCreateFile:
1568
 * @file:  a FILE*
1569
 * @enc:  the charset encoding if known (deprecated)
1570
 *
1571
 * DEPRECATED: Don't use.
1572
 *
1573
 * Create a buffered parser input for the progressive parsing of a FILE *
1574
 * buffered C I/O
1575
 *
1576
 * The encoding argument is deprecated and should be set to
1577
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1578
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1579
 *
1580
 * Returns the new parser input or NULL
1581
 */
1582
xmlParserInputBufferPtr
1583
0
xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
1584
0
    xmlParserInputBufferPtr ret;
1585
1586
0
    if (file == NULL) return(NULL);
1587
1588
0
    ret = xmlAllocParserInputBuffer(enc);
1589
0
    if (ret != NULL) {
1590
0
        ret->context = file;
1591
0
  ret->readcallback = xmlFileRead;
1592
0
  ret->closecallback = NULL;
1593
0
    }
1594
1595
0
    return(ret);
1596
0
}
1597
1598
#ifdef LIBXML_OUTPUT_ENABLED
1599
/**
1600
 * xmlOutputBufferCreateFile:
1601
 * @file:  a FILE*
1602
 * @encoder:  the encoding converter or NULL
1603
 *
1604
 * Create a buffered output for the progressive saving to a FILE *
1605
 * buffered C I/O
1606
 *
1607
 * Consumes @encoder even in error case.
1608
 *
1609
 * Returns the new parser output or NULL
1610
 */
1611
xmlOutputBufferPtr
1612
0
xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
1613
0
    xmlOutputBufferPtr ret;
1614
1615
0
    if (file == NULL) return(NULL);
1616
1617
0
    ret = xmlAllocOutputBuffer(encoder);
1618
0
    if (ret != NULL) {
1619
0
        ret->context = file;
1620
0
  ret->writecallback = xmlFileWrite;
1621
0
  ret->closecallback = xmlFileFlush;
1622
0
    }
1623
1624
0
    return(ret);
1625
0
}
1626
1627
/**
1628
 * xmlOutputBufferCreateBuffer:
1629
 * @buffer:  a xmlBufferPtr
1630
 * @encoder:  the encoding converter or NULL
1631
 *
1632
 * Create a buffered output for the progressive saving to a xmlBuffer
1633
 *
1634
 * Consumes @encoder even in error case.
1635
 *
1636
 * Returns the new parser output or NULL
1637
 */
1638
xmlOutputBufferPtr
1639
xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
1640
0
                            xmlCharEncodingHandlerPtr encoder) {
1641
0
    xmlOutputBufferPtr ret;
1642
1643
0
    if (buffer == NULL) return(NULL);
1644
1645
0
    ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
1646
0
                                  encoder);
1647
1648
0
    return(ret);
1649
0
}
1650
1651
/**
1652
 * xmlOutputBufferGetContent:
1653
 * @out:  an xmlOutputBufferPtr
1654
 *
1655
 * Gives a pointer to the data currently held in the output buffer
1656
 *
1657
 * Returns a pointer to the data or NULL in case of error
1658
 */
1659
const xmlChar *
1660
0
xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
1661
0
    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1662
0
        return(NULL);
1663
1664
0
    return(xmlBufContent(out->buffer));
1665
0
}
1666
1667
/**
1668
 * xmlOutputBufferGetSize:
1669
 * @out:  an xmlOutputBufferPtr
1670
 *
1671
 * Gives the length of the data currently held in the output buffer
1672
 *
1673
 * Returns 0 in case or error or no data is held, the size otherwise
1674
 */
1675
size_t
1676
0
xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
1677
0
    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1678
0
        return(0);
1679
1680
0
    return(xmlBufUse(out->buffer));
1681
0
}
1682
1683
1684
#endif /* LIBXML_OUTPUT_ENABLED */
1685
1686
/**
1687
 * xmlParserInputBufferCreateFd:
1688
 * @fd:  a file descriptor number
1689
 * @enc:  the charset encoding if known (deprecated)
1690
 *
1691
 * DEPRECATED: Use xmlNewInputFromFd.
1692
 *
1693
 * Create a buffered parser input for the progressive parsing for the input
1694
 * from a file descriptor
1695
 *
1696
 * The encoding argument is deprecated and should be set to
1697
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1698
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1699
 *
1700
 * Returns the new parser input or NULL
1701
 */
1702
xmlParserInputBufferPtr
1703
0
xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1704
0
    xmlParserInputBufferPtr ret;
1705
1706
0
    if (fd < 0) return(NULL);
1707
1708
0
    ret = xmlAllocParserInputBuffer(enc);
1709
0
    if (ret != NULL) {
1710
0
        ret->context = (void *) (ptrdiff_t) fd;
1711
0
  ret->readcallback = xmlFdRead;
1712
0
    }
1713
1714
0
    return(ret);
1715
0
}
1716
1717
typedef struct {
1718
    const char *cur;
1719
    size_t size;
1720
} xmlMemIOCtxt;
1721
1722
static int
1723
94.5k
xmlMemRead(void *vctxt, char *buf, int size) {
1724
94.5k
    xmlMemIOCtxt *ctxt = vctxt;
1725
1726
94.5k
    if ((size_t) size > ctxt->size)
1727
36.1k
        size = ctxt->size;
1728
1729
94.5k
    memcpy(buf, ctxt->cur, size);
1730
94.5k
    ctxt->cur += size;
1731
94.5k
    ctxt->size -= size;
1732
1733
94.5k
    return size;
1734
94.5k
}
1735
1736
static int
1737
20.2k
xmlMemClose(void *vctxt) {
1738
20.2k
    xmlMemIOCtxt *ctxt = vctxt;
1739
1740
20.2k
    xmlFree(ctxt);
1741
20.2k
    return(0);
1742
20.2k
}
1743
1744
/**
1745
 * xmlNewInputBufferMemory:
1746
 * @mem:  memory buffer
1747
 * @size:  size of buffer
1748
 * @flags:  flags
1749
 * @enc:  the charset encoding if known (deprecated)
1750
 *
1751
 * Create an input buffer for memory.
1752
 *
1753
 * Returns the new input buffer or NULL.
1754
 */
1755
xmlParserInputBufferPtr
1756
xmlNewInputBufferMemory(const void *mem, size_t size, int flags,
1757
20.2k
                        xmlCharEncoding enc) {
1758
20.2k
    xmlParserInputBufferPtr ret;
1759
1760
20.2k
    if ((flags & XML_INPUT_BUF_STATIC) &&
1761
20.2k
        ((flags & XML_INPUT_BUF_ZERO_TERMINATED) == 0)) {
1762
20.2k
        xmlMemIOCtxt *ctxt;
1763
1764
        /*
1765
         * Static buffer without zero terminator.
1766
         * Stream memory to avoid a copy.
1767
         */
1768
20.2k
        ret = xmlAllocParserInputBuffer(enc);
1769
20.2k
        if (ret == NULL)
1770
0
            return(NULL);
1771
1772
20.2k
        ctxt = xmlMalloc(sizeof(*ctxt));
1773
20.2k
        if (ctxt == NULL) {
1774
0
            xmlFreeParserInputBuffer(ret);
1775
0
            return(NULL);
1776
0
        }
1777
1778
20.2k
        ctxt->cur = mem;
1779
20.2k
        ctxt->size = size;
1780
1781
20.2k
        ret->context = ctxt;
1782
20.2k
        ret->readcallback = xmlMemRead;
1783
20.2k
        ret->closecallback = xmlMemClose;
1784
20.2k
    } else {
1785
0
        ret = xmlMalloc(sizeof(*ret));
1786
0
        if (ret == NULL)
1787
0
            return(NULL);
1788
0
        memset(ret, 0, sizeof(xmlParserInputBuffer));
1789
0
        ret->compressed = -1;
1790
1791
0
        ret->buffer = xmlBufCreateMem((const xmlChar *) mem, size,
1792
0
                                      (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1793
0
        if (ret->buffer == NULL) {
1794
0
            xmlFree(ret);
1795
0
            return(NULL);
1796
0
        }
1797
0
    }
1798
1799
20.2k
    return(ret);
1800
20.2k
}
1801
1802
/**
1803
 * xmlParserInputBufferCreateMem:
1804
 * @mem:  the memory input
1805
 * @size:  the length of the memory block
1806
 * @enc:  the charset encoding if known (deprecated)
1807
 *
1808
 * DEPRECATED: Use xmlNewInputFromMemory.
1809
 *
1810
 * Create a parser input buffer for parsing from a memory area.
1811
 *
1812
 * This function makes a copy of the whole input buffer. If you are sure
1813
 * that the contents of the buffer will remain valid until the document
1814
 * was parsed, you can avoid the copy by using
1815
 * xmlParserInputBufferCreateStatic.
1816
 *
1817
 * The encoding argument is deprecated and should be set to
1818
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1819
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1820
 *
1821
 * Returns the new parser input or NULL in case of error.
1822
 */
1823
xmlParserInputBufferPtr
1824
0
xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
1825
0
    if ((mem == NULL) || (size < 0))
1826
0
        return(NULL);
1827
1828
0
    return(xmlNewInputBufferMemory(mem, size, 0, enc));
1829
0
}
1830
1831
/**
1832
 * xmlParserInputBufferCreateStatic:
1833
 * @mem:  the memory input
1834
 * @size:  the length of the memory block
1835
 * @enc:  the charset encoding if known
1836
 *
1837
 * DEPRECATED: Use xmlNewInputFromMemory.
1838
 *
1839
 * Create a parser input buffer for parsing from a memory area.
1840
 *
1841
 * This functions assumes that the contents of the input buffer remain
1842
 * valid until the document was parsed. Use xmlParserInputBufferCreateMem
1843
 * otherwise.
1844
 *
1845
 * The encoding argument is deprecated and should be set to
1846
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1847
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1848
 *
1849
 * Returns the new parser input or NULL in case of error.
1850
 */
1851
xmlParserInputBufferPtr
1852
xmlParserInputBufferCreateStatic(const char *mem, int size,
1853
0
                                 xmlCharEncoding enc) {
1854
0
    if ((mem == NULL) || (size < 0))
1855
0
        return(NULL);
1856
1857
0
    return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
1858
0
}
1859
1860
/**
1861
 * xmlNewInputBufferString:
1862
 * @str:  C string
1863
 * @flags:  flags
1864
 *
1865
 * DEPRECATED: Use xmlNewInputFromString.
1866
 *
1867
 * Create an input buffer for a null-terminated C string.
1868
 *
1869
 * Returns the new input buffer or NULL.
1870
 */
1871
xmlParserInputBufferPtr
1872
18.5k
xmlNewInputBufferString(const char *str, int flags) {
1873
18.5k
    xmlParserInputBufferPtr ret;
1874
1875
18.5k
    ret = xmlMalloc(sizeof(*ret));
1876
18.5k
    if (ret == NULL)
1877
0
  return(NULL);
1878
18.5k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
1879
18.5k
    ret->compressed = -1;
1880
1881
18.5k
    ret->buffer = xmlBufCreateMem((const xmlChar *) str, strlen(str),
1882
18.5k
                                  (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1883
18.5k
    if (ret->buffer == NULL) {
1884
0
        xmlFree(ret);
1885
0
  return(NULL);
1886
0
    }
1887
1888
18.5k
    return(ret);
1889
18.5k
}
1890
1891
#ifdef LIBXML_OUTPUT_ENABLED
1892
/**
1893
 * xmlOutputBufferCreateFd:
1894
 * @fd:  a file descriptor number
1895
 * @encoder:  the encoding converter or NULL
1896
 *
1897
 * Create a buffered output for the progressive saving
1898
 * to a file descriptor
1899
 *
1900
 * Consumes @encoder even in error case.
1901
 *
1902
 * Returns the new parser output or NULL
1903
 */
1904
xmlOutputBufferPtr
1905
0
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
1906
0
    xmlOutputBufferPtr ret;
1907
1908
0
    if (fd < 0) return(NULL);
1909
1910
0
    ret = xmlAllocOutputBuffer(encoder);
1911
0
    if (ret != NULL) {
1912
0
        ret->context = (void *) (ptrdiff_t) fd;
1913
0
  ret->writecallback = xmlFdWrite;
1914
0
  ret->closecallback = NULL;
1915
0
    }
1916
1917
0
    return(ret);
1918
0
}
1919
#endif /* LIBXML_OUTPUT_ENABLED */
1920
1921
/**
1922
 * xmlParserInputBufferCreateIO:
1923
 * @ioread:  an I/O read function
1924
 * @ioclose:  an I/O close function
1925
 * @ioctx:  an I/O handler
1926
 * @enc:  the charset encoding if known (deprecated)
1927
 *
1928
 * DEPRECATED: Use xmlNewInputFromIO.
1929
 *
1930
 * Create a buffered parser input for the progressive parsing for the input
1931
 * from an I/O handler
1932
 *
1933
 * The encoding argument is deprecated and should be set to
1934
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1935
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1936
 *
1937
 * Returns the new parser input or NULL
1938
 */
1939
xmlParserInputBufferPtr
1940
xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
1941
0
   xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
1942
0
    xmlParserInputBufferPtr ret;
1943
1944
0
    if (ioread == NULL) return(NULL);
1945
1946
0
    ret = xmlAllocParserInputBuffer(enc);
1947
0
    if (ret != NULL) {
1948
0
        ret->context = (void *) ioctx;
1949
0
  ret->readcallback = ioread;
1950
0
  ret->closecallback = ioclose;
1951
0
    }
1952
1953
0
    return(ret);
1954
0
}
1955
1956
#ifdef LIBXML_OUTPUT_ENABLED
1957
/**
1958
 * xmlOutputBufferCreateIO:
1959
 * @iowrite:  an I/O write function
1960
 * @ioclose:  an I/O close function
1961
 * @ioctx:  an I/O handler
1962
 * @encoder:  the charset encoding if known
1963
 *
1964
 * Create a buffered output for the progressive saving
1965
 * to an I/O handler
1966
 *
1967
 * Consumes @encoder even in error case.
1968
 *
1969
 * Returns the new parser output or NULL
1970
 */
1971
xmlOutputBufferPtr
1972
xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
1973
   xmlOutputCloseCallback  ioclose, void *ioctx,
1974
0
   xmlCharEncodingHandlerPtr encoder) {
1975
0
    xmlOutputBufferPtr ret;
1976
1977
0
    if (iowrite == NULL) {
1978
0
        xmlCharEncCloseFunc(encoder);
1979
0
        return(NULL);
1980
0
    }
1981
1982
0
    ret = xmlAllocOutputBuffer(encoder);
1983
0
    if (ret != NULL) {
1984
0
        ret->context = (void *) ioctx;
1985
0
  ret->writecallback = iowrite;
1986
0
  ret->closecallback = ioclose;
1987
0
    }
1988
1989
0
    return(ret);
1990
0
}
1991
#endif /* LIBXML_OUTPUT_ENABLED */
1992
1993
/**
1994
 * xmlParserInputBufferCreateFilenameDefault:
1995
 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
1996
 *
1997
 * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions.
1998
 *
1999
 * Registers a callback for URI input file handling
2000
 *
2001
 * Returns the old value of the registration function
2002
 */
2003
xmlParserInputBufferCreateFilenameFunc
2004
xmlParserInputBufferCreateFilenameDefault(
2005
        xmlParserInputBufferCreateFilenameFunc func)
2006
0
{
2007
0
    xmlParserInputBufferCreateFilenameFunc old;
2008
2009
0
    old = xmlParserInputBufferCreateFilenameValue;
2010
0
    if (old == NULL)
2011
0
        old = __xmlParserInputBufferCreateFilename;
2012
2013
0
    if (func == __xmlParserInputBufferCreateFilename)
2014
0
        func = NULL;
2015
0
    xmlParserInputBufferCreateFilenameValue = func;
2016
0
    return(old);
2017
0
}
2018
2019
/**
2020
 * xmlOutputBufferCreateFilenameDefault:
2021
 * @func: function pointer to the new OutputBufferCreateFilenameFunc
2022
 *
2023
 * Registers a callback for URI output file handling
2024
 *
2025
 * Returns the old value of the registration function
2026
 */
2027
xmlOutputBufferCreateFilenameFunc
2028
xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
2029
0
{
2030
0
    xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
2031
0
#ifdef LIBXML_OUTPUT_ENABLED
2032
0
    if (old == NULL) {
2033
0
    old = __xmlOutputBufferCreateFilename;
2034
0
  }
2035
0
#endif
2036
0
    xmlOutputBufferCreateFilenameValue = func;
2037
0
    return(old);
2038
0
}
2039
2040
/**
2041
 * xmlParserInputBufferPush:
2042
 * @in:  a buffered parser input
2043
 * @len:  the size in bytes of the array.
2044
 * @buf:  an char array
2045
 *
2046
 * DEPRECATED: Internal function, don't use.
2047
 *
2048
 * Push the content of the arry in the input buffer
2049
 * This routine handle the I18N transcoding to internal UTF-8
2050
 * This is used when operating the parser in progressive (push) mode.
2051
 *
2052
 * Returns the number of chars read and stored in the buffer, or -1
2053
 *         in case of error.
2054
 */
2055
int
2056
xmlParserInputBufferPush(xmlParserInputBufferPtr in,
2057
0
                   int len, const char *buf) {
2058
0
    size_t nbchars = 0;
2059
0
    int ret;
2060
2061
0
    if (len < 0) return(0);
2062
0
    if ((in == NULL) || (in->error)) return(-1);
2063
0
    if (in->encoder != NULL) {
2064
        /*
2065
   * Store the data in the incoming raw buffer
2066
   */
2067
0
        if (in->raw == NULL) {
2068
0
      in->raw = xmlBufCreate(50);
2069
0
            if (in->raw == NULL) {
2070
0
                in->error = XML_ERR_NO_MEMORY;
2071
0
                return(-1);
2072
0
            }
2073
0
  }
2074
0
  ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
2075
0
  if (ret != 0) {
2076
0
            in->error = XML_ERR_NO_MEMORY;
2077
0
      return(-1);
2078
0
        }
2079
2080
  /*
2081
   * convert as much as possible to the parser reading buffer.
2082
   */
2083
0
        nbchars = SIZE_MAX;
2084
0
  if (xmlCharEncInput(in, &nbchars) < 0)
2085
0
            return(-1);
2086
0
        if (nbchars > INT_MAX)
2087
0
            nbchars = INT_MAX;
2088
0
    } else {
2089
0
  nbchars = len;
2090
0
        ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
2091
0
  if (ret != 0) {
2092
0
            in->error = XML_ERR_NO_MEMORY;
2093
0
      return(-1);
2094
0
        }
2095
0
    }
2096
0
    return(nbchars);
2097
0
}
2098
2099
/**
2100
 * endOfInput:
2101
 *
2102
 * When reading from an Input channel indicated end of file or error
2103
 * don't reread from it again.
2104
 */
2105
static int
2106
endOfInput (void * context ATTRIBUTE_UNUSED,
2107
      char * buffer ATTRIBUTE_UNUSED,
2108
1.28M
      int len ATTRIBUTE_UNUSED) {
2109
1.28M
    return(0);
2110
1.28M
}
2111
2112
/**
2113
 * xmlParserInputBufferGrow:
2114
 * @in:  a buffered parser input
2115
 * @len:  indicative value of the amount of chars to read
2116
 *
2117
 * DEPRECATED: Internal function, don't use.
2118
 *
2119
 * Grow up the content of the input buffer, the old data are preserved
2120
 * This routine handle the I18N transcoding to internal UTF-8
2121
 * This routine is used when operating the parser in normal (pull) mode
2122
 *
2123
 * Returns the number of chars read and stored in the buffer, or -1
2124
 *         in case of error.
2125
 */
2126
int
2127
1.37M
xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
2128
1.37M
    int res = 0;
2129
2130
1.37M
    if ((in == NULL) || (in->error))
2131
0
        return(-1);
2132
2133
1.37M
    if (len < MINLEN)
2134
1.37M
        len = MINLEN;
2135
2136
    /*
2137
     * Call the read method for this I/O type.
2138
     */
2139
1.37M
    if (in->readcallback != NULL) {
2140
1.37M
        xmlBufPtr buf;
2141
2142
1.37M
        if (in->encoder == NULL) {
2143
1.12M
            buf = in->buffer;
2144
1.12M
        } else {
2145
            /*
2146
             * Some users only set 'encoder' and expect us to create
2147
             * the raw buffer lazily.
2148
             */
2149
254k
            if (in->raw == NULL) {
2150
0
                in->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
2151
0
                if (in->raw == NULL) {
2152
0
                    in->error = XML_ERR_NO_MEMORY;
2153
0
                    return(-1);
2154
0
                }
2155
0
            }
2156
254k
            buf = in->raw;
2157
254k
        }
2158
2159
1.37M
        if (xmlBufGrow(buf, len) < 0) {
2160
0
            in->error = XML_ERR_NO_MEMORY;
2161
0
            return(-1);
2162
0
        }
2163
2164
1.37M
  res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
2165
1.37M
  if (res <= 0)
2166
1.30M
      in->readcallback = endOfInput;
2167
1.37M
        if (res < 0) {
2168
0
            if (res == -1)
2169
0
                in->error = XML_IO_UNKNOWN;
2170
0
            else
2171
0
                in->error = -res;
2172
0
            return(-1);
2173
0
        }
2174
2175
1.37M
        if (xmlBufAddLen(buf, res) < 0) {
2176
0
            in->error = XML_ERR_NO_MEMORY;
2177
0
            return(-1);
2178
0
        }
2179
1.37M
    }
2180
2181
    /*
2182
     * Handle encoding.
2183
     */
2184
1.37M
    if (in->encoder != NULL) {
2185
254k
        size_t sizeOut;
2186
2187
        /*
2188
         * Don't convert whole buffer when reading from memory.
2189
         */
2190
254k
        if (in->readcallback == NULL)
2191
0
            sizeOut = len;
2192
254k
        else
2193
254k
            sizeOut = SIZE_MAX;
2194
2195
254k
  if (xmlCharEncInput(in, &sizeOut) < 0)
2196
190
      return(-1);
2197
254k
        res = sizeOut;
2198
254k
    }
2199
1.37M
    return(res);
2200
1.37M
}
2201
2202
/**
2203
 * xmlParserInputBufferRead:
2204
 * @in:  a buffered parser input
2205
 * @len:  indicative value of the amount of chars to read
2206
 *
2207
 * DEPRECATED: Internal function, don't use.
2208
 *
2209
 * Same as xmlParserInputBufferGrow.
2210
 *
2211
 * Returns the number of chars read and stored in the buffer, or -1
2212
 *         in case of error.
2213
 */
2214
int
2215
0
xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
2216
0
    return(xmlParserInputBufferGrow(in, len));
2217
0
}
2218
2219
#ifdef LIBXML_OUTPUT_ENABLED
2220
/**
2221
 * xmlOutputBufferWrite:
2222
 * @out:  a buffered parser output
2223
 * @len:  the size in bytes of the array.
2224
 * @data:  an char array
2225
 *
2226
 * Write the content of the array in the output I/O buffer
2227
 * This routine handle the I18N transcoding from internal UTF-8
2228
 * The buffer is lossless, i.e. will store in case of partial
2229
 * or delayed writes.
2230
 *
2231
 * Returns the number of chars immediately written, or -1
2232
 *         in case of error.
2233
 */
2234
int
2235
0
xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *data) {
2236
0
    size_t written = 0;
2237
2238
0
    if ((out == NULL) || (out->error))
2239
0
        return(-1);
2240
0
    if (len < 0)
2241
0
        return(0);
2242
2243
0
    while (len > 0) {
2244
0
        xmlBufPtr buf = NULL;
2245
0
        int chunk;
2246
0
        int ret;
2247
2248
0
  chunk = len;
2249
0
  if (chunk > 256 * 1024)
2250
0
      chunk = 256 * 1024;
2251
2252
0
        ret = xmlBufAdd(out->buffer, (const xmlChar *) data, chunk);
2253
0
        if (ret != 0) {
2254
0
            out->error = XML_ERR_NO_MEMORY;
2255
0
            return(-1);
2256
0
        }
2257
2258
  /*
2259
   * first handle encoding stuff.
2260
   */
2261
0
  if (out->encoder != NULL) {
2262
      /*
2263
       * Store the data in the incoming raw buffer
2264
       */
2265
0
      if (out->conv == NULL) {
2266
0
    out->conv = xmlBufCreate(MINLEN);
2267
0
                if (out->conv == NULL) {
2268
0
                    out->error = XML_ERR_NO_MEMORY;
2269
0
                    return(-1);
2270
0
                }
2271
0
      }
2272
2273
      /*
2274
       * convert as much as possible to the parser reading buffer.
2275
       */
2276
0
            if (xmlBufUse(out->buffer) < 256) {
2277
0
                ret = 0;
2278
0
            } else {
2279
0
                ret = xmlCharEncOutput(out, 0);
2280
0
                if (ret < 0)
2281
0
                    return(-1);
2282
0
            }
2283
2284
0
            if (out->writecallback)
2285
0
                buf = out->conv;
2286
0
            else
2287
0
                written += ret;
2288
0
  } else {
2289
0
            if (out->writecallback)
2290
0
          buf = out->buffer;
2291
0
            else
2292
0
                written += chunk;
2293
0
  }
2294
0
  data += chunk;
2295
0
  len -= chunk;
2296
2297
0
  if ((buf != NULL) && (out->writecallback)) {
2298
      /*
2299
       * second write the stuff to the I/O channel
2300
       */
2301
0
      while (1) {
2302
0
                size_t nbchars = xmlBufUse(buf);
2303
2304
0
                if (nbchars < MINLEN)
2305
0
                    break;
2306
0
                if (nbchars > 256 * 1024)
2307
0
                    nbchars = 256 * 1024;
2308
2309
0
    ret = out->writecallback(out->context,
2310
0
                           (const char *)xmlBufContent(buf), nbchars);
2311
0
                if (ret < 0) {
2312
0
                    out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2313
0
                    return(-1);
2314
0
                }
2315
0
                if ((ret == 0) || ((size_t) ret > nbchars)) {
2316
0
                    out->error = XML_ERR_INTERNAL_ERROR;
2317
0
                    return(-1);
2318
0
                }
2319
2320
0
    xmlBufShrink(buf, ret);
2321
0
          written += ret;
2322
0
                if (out->written > INT_MAX - ret)
2323
0
                    out->written = INT_MAX;
2324
0
                else
2325
0
                    out->written += ret;
2326
0
            }
2327
0
  }
2328
0
    }
2329
2330
0
    return(written <= INT_MAX ? written : INT_MAX);
2331
0
}
2332
2333
/**
2334
 * xmlOutputBufferWriteEscape:
2335
 * @out:  a buffered parser output
2336
 * @str:  a zero terminated UTF-8 string
2337
 * @escaping:  an optional escaping function (or NULL)
2338
 *
2339
 * Write the content of the string in the output I/O buffer
2340
 * This routine escapes the characters and then handle the I18N
2341
 * transcoding from internal UTF-8
2342
 * The buffer is lossless, i.e. will store in case of partial
2343
 * or delayed writes.
2344
 *
2345
 * Returns the number of chars immediately written, or -1
2346
 *         in case of error.
2347
 */
2348
int
2349
xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
2350
0
                           xmlCharEncodingOutputFunc escaping) {
2351
0
    int ret;
2352
0
    int written = 0;
2353
0
    size_t len;
2354
2355
0
    if ((out == NULL) || (out->error) || (str == NULL))
2356
0
        return(-1);
2357
2358
0
    len = strlen((const char *) str);
2359
0
    if (len >= INT_MAX) {
2360
0
        out->error = XML_ERR_RESOURCE_LIMIT;
2361
0
        return(-1);
2362
0
    }
2363
2364
0
    if (escaping == NULL) {
2365
0
        char *escaped = (char *) xmlEscapeText(str, XML_ESCAPE_ALLOW_INVALID);
2366
2367
0
        if (escaped == NULL) {
2368
0
            out->error = XML_ERR_NO_MEMORY;
2369
0
            return(-1);
2370
0
        }
2371
2372
0
        len = strlen(escaped);
2373
0
        if (len >= INT_MAX) {
2374
0
            out->error = XML_ERR_RESOURCE_LIMIT;
2375
0
            return(-1);
2376
0
        }
2377
2378
0
        ret = xmlOutputBufferWrite(out, len, escaped);
2379
2380
0
        xmlFree(escaped);
2381
0
        return(ret);
2382
0
    }
2383
2384
0
    while (len > 0) {
2385
0
        xmlChar buf[1024];
2386
0
        int c_out;
2387
0
        int c_in;
2388
2389
0
  c_out = 1024;
2390
0
  c_in = len;
2391
2392
0
        ret = escaping(buf, &c_out, str, &c_in);
2393
0
        if (ret < 0) {
2394
0
            out->error = XML_ERR_NO_MEMORY;
2395
0
            return(-1);
2396
0
        }
2397
0
        str += c_in;
2398
0
        len -= c_in;
2399
2400
0
        ret = xmlOutputBufferWrite(out, c_out, (char *) buf);
2401
0
        if (ret < 0)
2402
0
            return(ret);
2403
0
        written += ret;
2404
0
    }
2405
2406
0
    return(written);
2407
0
}
2408
2409
/**
2410
 * xmlOutputBufferWriteString:
2411
 * @out:  a buffered parser output
2412
 * @str:  a zero terminated C string
2413
 *
2414
 * Write the content of the string in the output I/O buffer
2415
 * This routine handle the I18N transcoding from internal UTF-8
2416
 * The buffer is lossless, i.e. will store in case of partial
2417
 * or delayed writes.
2418
 *
2419
 * Returns the number of chars immediately written, or -1
2420
 *         in case of error.
2421
 */
2422
int
2423
0
xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
2424
0
    int len;
2425
2426
0
    if ((out == NULL) || (out->error)) return(-1);
2427
0
    if (str == NULL)
2428
0
        return(-1);
2429
0
    len = strlen(str);
2430
2431
0
    if (len > 0)
2432
0
  return(xmlOutputBufferWrite(out, len, str));
2433
0
    return(len);
2434
0
}
2435
2436
/**
2437
 * xmlOutputBufferWriteQuotedString:
2438
 * @buf:  output buffer
2439
 * @string:  the string to add
2440
 *
2441
 * routine which manage and grows an output buffer. This one writes
2442
 * a quoted or double quoted #xmlChar string, checking first if it holds
2443
 * quote or double-quotes internally
2444
 */
2445
void
2446
xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,
2447
0
                                 const xmlChar *string) {
2448
0
    const xmlChar *cur, *base;
2449
2450
0
    if ((buf == NULL) || (buf->error))
2451
0
        return;
2452
2453
0
    if (xmlStrchr(string, '\"')) {
2454
0
        if (xmlStrchr(string, '\'')) {
2455
0
      xmlOutputBufferWrite(buf, 1, "\"");
2456
0
            base = cur = string;
2457
0
            while(*cur != 0){
2458
0
                if(*cur == '"'){
2459
0
                    if (base != cur)
2460
0
                        xmlOutputBufferWrite(buf, cur - base,
2461
0
                                             (const char *) base);
2462
0
                    xmlOutputBufferWrite(buf, 6, "&quot;");
2463
0
                    cur++;
2464
0
                    base = cur;
2465
0
                }
2466
0
                else {
2467
0
                    cur++;
2468
0
                }
2469
0
            }
2470
0
            if (base != cur)
2471
0
                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
2472
0
      xmlOutputBufferWrite(buf, 1, "\"");
2473
0
  }
2474
0
        else{
2475
0
      xmlOutputBufferWrite(buf, 1, "'");
2476
0
            xmlOutputBufferWriteString(buf, (const char *) string);
2477
0
      xmlOutputBufferWrite(buf, 1, "'");
2478
0
        }
2479
0
    } else {
2480
0
        xmlOutputBufferWrite(buf, 1, "\"");
2481
0
        xmlOutputBufferWriteString(buf, (const char *) string);
2482
0
        xmlOutputBufferWrite(buf, 1, "\"");
2483
0
    }
2484
0
}
2485
2486
/**
2487
 * xmlOutputBufferFlush:
2488
 * @out:  a buffered output
2489
 *
2490
 * flushes the output I/O channel
2491
 *
2492
 * Returns the number of byte written or -1 in case of error.
2493
 */
2494
int
2495
0
xmlOutputBufferFlush(xmlOutputBufferPtr out) {
2496
0
    int nbchars = 0, ret = 0;
2497
2498
0
    if ((out == NULL) || (out->error)) return(-1);
2499
    /*
2500
     * first handle encoding stuff.
2501
     */
2502
0
    if ((out->conv != NULL) && (out->encoder != NULL)) {
2503
  /*
2504
   * convert as much as possible to the parser output buffer.
2505
   */
2506
0
  do {
2507
0
      nbchars = xmlCharEncOutput(out, 0);
2508
0
      if (nbchars < 0)
2509
0
    return(-1);
2510
0
  } while (nbchars);
2511
0
    }
2512
2513
    /*
2514
     * second flush the stuff to the I/O channel
2515
     */
2516
0
    if ((out->conv != NULL) && (out->encoder != NULL) &&
2517
0
  (out->writecallback != NULL)) {
2518
0
  ret = out->writecallback(out->context,
2519
0
                                 (const char *)xmlBufContent(out->conv),
2520
0
                                 xmlBufUse(out->conv));
2521
0
  if (ret >= 0)
2522
0
      xmlBufShrink(out->conv, ret);
2523
0
    } else if (out->writecallback != NULL) {
2524
0
  ret = out->writecallback(out->context,
2525
0
                                 (const char *)xmlBufContent(out->buffer),
2526
0
                                 xmlBufUse(out->buffer));
2527
0
  if (ret >= 0)
2528
0
      xmlBufShrink(out->buffer, ret);
2529
0
    }
2530
0
    if (ret < 0) {
2531
0
        out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2532
0
  return(ret);
2533
0
    }
2534
0
    if (out->written > INT_MAX - ret)
2535
0
        out->written = INT_MAX;
2536
0
    else
2537
0
        out->written += ret;
2538
2539
0
    return(ret);
2540
0
}
2541
#endif /* LIBXML_OUTPUT_ENABLED */
2542
2543
/**
2544
 * xmlParserGetDirectory:
2545
 * @filename:  the path to a file
2546
 *
2547
 * lookup the directory for that file
2548
 *
2549
 * Returns a new allocated string containing the directory, or NULL.
2550
 */
2551
char *
2552
9.89k
xmlParserGetDirectory(const char *filename) {
2553
9.89k
    char *ret = NULL;
2554
9.89k
    char dir[1024];
2555
9.89k
    char *cur;
2556
2557
9.89k
    if (filename == NULL) return(NULL);
2558
2559
#if defined(_WIN32)
2560
#   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
2561
#else
2562
569k
#   define IS_XMLPGD_SEP(ch) (ch=='/')
2563
9.89k
#endif
2564
2565
9.89k
    strncpy(dir, filename, 1023);
2566
9.89k
    dir[1023] = 0;
2567
9.89k
    cur = &dir[strlen(dir)];
2568
568k
    while (cur > dir) {
2569
559k
         if (IS_XMLPGD_SEP(*cur)) break;
2570
559k
   cur --;
2571
559k
    }
2572
9.89k
    if (IS_XMLPGD_SEP(*cur)) {
2573
851
        if (cur == dir) dir[1] = 0;
2574
846
  else *cur = 0;
2575
851
  ret = xmlMemStrdup(dir);
2576
9.04k
    } else {
2577
9.04k
        ret = xmlMemStrdup(".");
2578
9.04k
    }
2579
9.89k
    return(ret);
2580
9.89k
#undef IS_XMLPGD_SEP
2581
9.89k
}
2582
2583
/**
2584
 * xmlNoNetExists:
2585
 * @filename:  the path to check
2586
 *
2587
 * DEPRECATED: Internal function, don't use.
2588
 *
2589
 * Like xmlCheckFilename but handles file URIs.
2590
 *
2591
 * Returns 0, 1, or 2.
2592
 */
2593
int
2594
0
xmlNoNetExists(const char *filename) {
2595
0
    char *fromUri;
2596
0
    int ret;
2597
2598
0
    if (filename == NULL)
2599
0
  return(0);
2600
2601
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
2602
0
        return(0);
2603
2604
0
    if (fromUri != NULL)
2605
0
        filename = fromUri;
2606
2607
0
    ret =  xmlCheckFilename(filename);
2608
2609
0
    xmlFree(fromUri);
2610
0
    return(ret);
2611
0
}
2612
2613
/************************************************************************
2614
 *                  *
2615
 *      Input/output callbacks        *
2616
 *                  *
2617
 ************************************************************************/
2618
2619
/**
2620
 * xmlInitIOCallbacks:
2621
 *
2622
 * Initialize callback tables.
2623
 */
2624
void
2625
xmlInitIOCallbacks(void)
2626
9.89k
{
2627
9.89k
    xmlInputCallbackNr = 1;
2628
9.89k
    xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2629
2630
9.89k
#ifdef LIBXML_OUTPUT_ENABLED
2631
9.89k
    xmlOutputCallbackNr = 1;
2632
9.89k
    xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2633
9.89k
#endif
2634
9.89k
}
2635
2636
/**
2637
 * xmlRegisterInputCallbacks:
2638
 * @matchFunc:  the xmlInputMatchCallback
2639
 * @openFunc:  the xmlInputOpenCallback
2640
 * @readFunc:  the xmlInputReadCallback
2641
 * @closeFunc:  the xmlInputCloseCallback
2642
 *
2643
 * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions.
2644
 *
2645
 * Register a new set of I/O callback for handling parser input.
2646
 *
2647
 * Returns the registered handler number or -1 in case of error
2648
 */
2649
int
2650
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2651
  xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2652
0
  xmlInputCloseCallback closeFunc) {
2653
0
    xmlInitParser();
2654
2655
0
    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2656
0
  return(-1);
2657
0
    }
2658
0
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2659
0
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2660
0
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2661
0
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2662
0
    return(xmlInputCallbackNr++);
2663
0
}
2664
2665
/**
2666
 * xmlRegisterDefaultInputCallbacks:
2667
 *
2668
 * Registers the default compiled-in I/O handlers.
2669
 */
2670
void
2671
0
xmlRegisterDefaultInputCallbacks(void) {
2672
0
    xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2673
0
}
2674
2675
/**
2676
 * xmlPopInputCallbacks:
2677
 *
2678
 * Clear the top input callback from the input stack. this includes the
2679
 * compiled-in I/O.
2680
 *
2681
 * Returns the number of input callback registered or -1 in case of error.
2682
 */
2683
int
2684
xmlPopInputCallbacks(void)
2685
0
{
2686
0
    xmlInitParser();
2687
2688
0
    if (xmlInputCallbackNr <= 0)
2689
0
        return(-1);
2690
2691
0
    xmlInputCallbackNr--;
2692
2693
0
    return(xmlInputCallbackNr);
2694
0
}
2695
2696
/**
2697
 * xmlCleanupInputCallbacks:
2698
 *
2699
 * clears the entire input callback table. this includes the
2700
 * compiled-in I/O.
2701
 */
2702
void
2703
xmlCleanupInputCallbacks(void)
2704
0
{
2705
0
    xmlInitParser();
2706
2707
0
    xmlInputCallbackNr = 0;
2708
0
}
2709
2710
#ifdef LIBXML_OUTPUT_ENABLED
2711
/**
2712
 * xmlRegisterOutputCallbacks:
2713
 * @matchFunc:  the xmlOutputMatchCallback
2714
 * @openFunc:  the xmlOutputOpenCallback
2715
 * @writeFunc:  the xmlOutputWriteCallback
2716
 * @closeFunc:  the xmlOutputCloseCallback
2717
 *
2718
 * Register a new set of I/O callback for handling output.
2719
 *
2720
 * Returns the registered handler number or -1 in case of error
2721
 */
2722
int
2723
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2724
  xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2725
0
  xmlOutputCloseCallback closeFunc) {
2726
0
    xmlInitParser();
2727
2728
0
    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2729
0
  return(-1);
2730
0
    }
2731
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2732
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2733
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2734
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2735
0
    return(xmlOutputCallbackNr++);
2736
0
}
2737
2738
/**
2739
 * xmlRegisterDefaultOutputCallbacks:
2740
 *
2741
 * Registers the default compiled-in I/O handlers.
2742
 */
2743
void
2744
0
xmlRegisterDefaultOutputCallbacks (void) {
2745
0
    xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2746
0
}
2747
2748
/**
2749
 * xmlPopOutputCallbacks:
2750
 *
2751
 * Remove the top output callbacks from the output stack. This includes the
2752
 * compiled-in I/O.
2753
 *
2754
 * Returns the number of output callback registered or -1 in case of error.
2755
 */
2756
int
2757
xmlPopOutputCallbacks(void)
2758
0
{
2759
0
    xmlInitParser();
2760
2761
0
    if (xmlOutputCallbackNr <= 0)
2762
0
        return(-1);
2763
2764
0
    xmlOutputCallbackNr--;
2765
2766
0
    return(xmlOutputCallbackNr);
2767
0
}
2768
2769
/**
2770
 * xmlCleanupOutputCallbacks:
2771
 *
2772
 * clears the entire output callback table. this includes the
2773
 * compiled-in I/O callbacks.
2774
 */
2775
void
2776
xmlCleanupOutputCallbacks(void)
2777
0
{
2778
0
    xmlInitParser();
2779
2780
0
    xmlOutputCallbackNr = 0;
2781
0
}
2782
2783
#ifdef LIBXML_HTTP_ENABLED
2784
/**
2785
 * xmlRegisterHTTPPostCallbacks:
2786
 *
2787
 * DEPRECATED: Support for HTTP POST has been removed.
2788
 */
2789
void
2790
xmlRegisterHTTPPostCallbacks(void) {
2791
    xmlRegisterDefaultOutputCallbacks();
2792
}
2793
#endif
2794
#endif /* LIBXML_OUTPUT_ENABLED */
2795