Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/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
  #define SIZE_MAX ((size_t) -1)
53
#endif
54
55
/* #define VERBOSE_FAILURE */
56
57
2.23M
#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 xmlParserErrors
126
xmlIOErr(int err)
127
0
{
128
0
    xmlParserErrors 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
typedef struct {
442
    int fd;
443
} xmlFdIOCtxt;
444
445
/**
446
 * xmlFdOpen:
447
 * @filename:  the URI for matching
448
 * @out:  pointer to resulting context
449
 *
450
 * Returns an xmlParserErrors code
451
 */
452
static xmlParserErrors
453
0
xmlFdOpen(const char *filename, int write, int *out) {
454
0
    char *fromUri = NULL;
455
0
    int flags;
456
0
    int fd;
457
0
    xmlParserErrors ret;
458
459
0
    *out = -1;
460
0
    if (filename == NULL)
461
0
        return(XML_ERR_ARGUMENT);
462
463
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
464
0
        return(XML_ERR_NO_MEMORY);
465
466
0
    if (fromUri != NULL)
467
0
        filename = fromUri;
468
469
#if defined(_WIN32)
470
    {
471
        wchar_t *wpath;
472
473
        wpath = __xmlIOWin32UTF8ToWChar(filename);
474
        if (wpath == NULL) {
475
            xmlFree(fromUri);
476
            return(XML_ERR_NO_MEMORY);
477
        }
478
        if (write)
479
            flags = _O_WRONLY | _O_CREAT | _O_TRUNC;
480
        else
481
            flags = _O_RDONLY;
482
  fd = _wopen(wpath, flags | _O_BINARY, 0666);
483
        xmlFree(wpath);
484
    }
485
#else
486
0
    if (write)
487
0
        flags = O_WRONLY | O_CREAT | O_TRUNC;
488
0
    else
489
0
        flags = O_RDONLY;
490
0
    fd = open(filename, flags, 0666);
491
0
#endif /* WIN32 */
492
493
0
    if (fd < 0) {
494
        /*
495
         * Windows and possibly other platforms return EINVAL
496
         * for invalid filenames.
497
         */
498
0
        if ((errno == ENOENT) || (errno == EINVAL)) {
499
0
            ret = XML_IO_ENOENT;
500
0
        } else {
501
0
            ret = xmlIOErr(errno);
502
0
        }
503
0
    } else {
504
0
        *out = fd;
505
0
        ret = XML_ERR_OK;
506
0
    }
507
508
0
    xmlFree(fromUri);
509
0
    return(ret);
510
0
}
511
512
/**
513
 * xmlFdRead:
514
 * @context:  the I/O context
515
 * @buffer:  where to drop data
516
 * @len:  number of bytes to read
517
 *
518
 * Read @len bytes to @buffer from the I/O channel.
519
 *
520
 * Returns the number of bytes read
521
 */
522
static int
523
0
xmlFdRead(void *context, char *buffer, int len) {
524
0
    xmlFdIOCtxt *fdctxt = context;
525
0
    int fd = fdctxt->fd;
526
0
    int ret = 0;
527
0
    int bytes;
528
529
0
    while (len > 0) {
530
0
        bytes = read(fd, buffer, len);
531
0
        if (bytes < 0) {
532
            /*
533
             * If we already got some bytes, return them without
534
             * raising an error.
535
             */
536
0
            if (ret > 0)
537
0
                break;
538
0
            return(-xmlIOErr(errno));
539
0
        }
540
0
        if (bytes == 0)
541
0
            break;
542
0
        ret += bytes;
543
0
        buffer += bytes;
544
0
        len -= bytes;
545
0
    }
546
547
0
    return(ret);
548
0
}
549
550
#ifdef LIBXML_OUTPUT_ENABLED
551
/**
552
 * xmlFdWrite:
553
 * @context:  the I/O context
554
 * @buffer:  where to get data
555
 * @len:  number of bytes to write
556
 *
557
 * Write @len bytes from @buffer to the I/O channel.
558
 *
559
 * Returns the number of bytes written
560
 */
561
static int
562
0
xmlFdWrite(void *context, const char *buffer, int len) {
563
0
    xmlFdIOCtxt *fdctxt = context;
564
0
    int fd = fdctxt->fd;
565
0
    int ret = 0;
566
0
    int bytes;
567
568
0
    while (len > 0) {
569
0
  bytes = write(fd, buffer, len);
570
0
  if (bytes < 0)
571
0
            return(-xmlIOErr(errno));
572
0
        ret += bytes;
573
0
        buffer += bytes;
574
0
        len -= bytes;
575
0
    }
576
577
0
    return(ret);
578
0
}
579
#endif /* LIBXML_OUTPUT_ENABLED */
580
581
static int
582
0
xmlFdFree(void *context) {
583
0
    xmlFree(context);
584
0
    return(XML_ERR_OK);
585
0
}
586
587
/**
588
 * xmlFdClose:
589
 * @context:  the I/O context
590
 *
591
 * Close an I/O channel
592
 *
593
 * Returns 0 in case of success and error code otherwise
594
 */
595
static int
596
0
xmlFdClose (void * context) {
597
0
    xmlFdIOCtxt *fdctxt = context;
598
0
    int fd = fdctxt->fd;
599
0
    int ret;
600
601
0
    ret = close(fd);
602
603
0
    xmlFree(fdctxt);
604
605
0
    if (ret < 0)
606
0
        return(xmlIOErr(errno));
607
608
0
    return(XML_ERR_OK);
609
0
}
610
611
/**
612
 * xmlFileMatch:
613
 * @filename:  the URI for matching
614
 *
615
 * DEPRECATED: Internal function, don't use.
616
 *
617
 * Returns 1 if matches, 0 otherwise
618
 */
619
int
620
0
xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
621
0
    return(1);
622
0
}
623
624
/**
625
 * xmlFileOpenSafe:
626
 * @filename:  the URI for matching
627
 * @out:  pointer to resulting context
628
 *
629
 * input from FILE *
630
 *
631
 * Returns an xmlParserErrors code
632
 */
633
static xmlParserErrors
634
0
xmlFileOpenSafe(const char *filename, int write, void **out) {
635
0
    char *fromUri = NULL;
636
0
    FILE *fd;
637
0
    xmlParserErrors ret = XML_ERR_OK;
638
639
0
    *out = NULL;
640
0
    if (filename == NULL)
641
0
        return(XML_ERR_ARGUMENT);
642
643
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
644
0
        return(XML_ERR_NO_MEMORY);
645
646
0
    if (fromUri != NULL)
647
0
        filename = fromUri;
648
649
#if defined(_WIN32)
650
    {
651
        wchar_t *wpath;
652
653
        wpath = __xmlIOWin32UTF8ToWChar(filename);
654
        if (wpath == NULL) {
655
            xmlFree(fromUri);
656
            return(XML_ERR_NO_MEMORY);
657
        }
658
  fd = _wfopen(wpath, write ? L"wb" : L"rb");
659
        xmlFree(wpath);
660
    }
661
#else
662
0
    fd = fopen(filename, write ? "wb" : "rb");
663
0
#endif /* WIN32 */
664
665
0
    if (fd == NULL) {
666
        /*
667
         * Windows and possibly other platforms return EINVAL
668
         * for invalid filenames.
669
         */
670
0
        if ((errno == ENOENT) || (errno == EINVAL)) {
671
0
            ret = XML_IO_ENOENT;
672
0
        } else {
673
            /*
674
             * This error won't be forwarded to the parser context
675
             * which will report it a second time.
676
             */
677
0
            ret = xmlIOErr(errno);
678
0
        }
679
0
    }
680
681
0
    *out = fd;
682
0
    xmlFree(fromUri);
683
0
    return(ret);
684
0
}
685
686
/**
687
 * xmlFileOpen:
688
 * @filename:  the URI for matching
689
 *
690
 * DEPRECATED: Internal function, don't use.
691
 *
692
 * Returns an IO context or NULL in case or failure
693
 */
694
void *
695
0
xmlFileOpen(const char *filename) {
696
0
    void *context;
697
698
0
    xmlFileOpenSafe(filename, 0, &context);
699
0
    return(context);
700
0
}
701
702
/**
703
 * xmlFileRead:
704
 * @context:  the I/O context
705
 * @buffer:  where to drop data
706
 * @len:  number of bytes to write
707
 *
708
 * DEPRECATED: Internal function, don't use.
709
 *
710
 * Returns the number of bytes read or < 0 in case of failure
711
 */
712
int
713
0
xmlFileRead(void * context, char * buffer, int len) {
714
0
    FILE *file = context;
715
0
    size_t bytes;
716
717
0
    if ((context == NULL) || (buffer == NULL))
718
0
        return(-1);
719
720
    /*
721
     * The C standard doesn't mandate that fread sets errno, only
722
     * POSIX does. The Windows documentation isn't really clear.
723
     * Set errno to zero which will be reported as unknown error
724
     * if fread fails without setting errno.
725
     */
726
0
    errno = 0;
727
0
    bytes = fread(buffer, 1, len, file);
728
0
    if ((bytes < (size_t) len) && (ferror(file)))
729
0
        return(-xmlIOErr(errno));
730
731
0
    return(bytes);
732
0
}
733
734
#ifdef LIBXML_OUTPUT_ENABLED
735
/**
736
 * xmlFileWrite:
737
 * @context:  the I/O context
738
 * @buffer:  where to drop data
739
 * @len:  number of bytes to write
740
 *
741
 * Write @len bytes from @buffer to the I/O channel.
742
 *
743
 * Returns the number of bytes written
744
 */
745
static int
746
0
xmlFileWrite(void *context, const char *buffer, int len) {
747
0
    FILE *file = context;
748
0
    size_t bytes;
749
750
0
    if ((context == NULL) || (buffer == NULL))
751
0
        return(-1);
752
753
0
    errno = 0;
754
0
    bytes = fwrite(buffer, 1, len, file);
755
0
    if (bytes < (size_t) len)
756
0
        return(-xmlIOErr(errno));
757
758
0
    return(len);
759
0
}
760
#endif /* LIBXML_OUTPUT_ENABLED */
761
762
/**
763
 * xmlFileFlush:
764
 * @context:  the I/O context
765
 *
766
 * Flush an I/O channel
767
 */
768
static int
769
0
xmlFileFlush (void * context) {
770
0
    FILE *file = context;
771
772
0
    if (file == NULL)
773
0
        return(-1);
774
775
0
    if (fflush(file) != 0)
776
0
        return(xmlIOErr(errno));
777
778
0
    return(XML_ERR_OK);
779
0
}
780
781
/**
782
 * xmlFileClose:
783
 * @context:  the I/O context
784
 *
785
 * DEPRECATED: Internal function, don't use.
786
 *
787
 * Returns 0 or -1 an error code case of error
788
 */
789
int
790
0
xmlFileClose (void * context) {
791
0
    FILE *file = context;
792
793
0
    if (context == NULL)
794
0
        return(-1);
795
796
0
    if (file == stdin)
797
0
        return(0);
798
0
    if ((file == stdout) || (file == stderr))
799
0
        return(xmlFileFlush(file));
800
801
0
    if (fclose(file) != 0)
802
0
        return(xmlIOErr(errno));
803
804
0
    return(0);
805
0
}
806
807
#ifdef LIBXML_OUTPUT_ENABLED
808
/**
809
 * xmlBufferWrite:
810
 * @context:  the xmlBuffer
811
 * @buffer:  the data to write
812
 * @len:  number of bytes to write
813
 *
814
 * Write @len bytes from @buffer to the xml buffer
815
 *
816
 * Returns the number of bytes written or a negative xmlParserErrors
817
 * value.
818
 */
819
static int
820
0
xmlBufferWrite (void * context, const char * buffer, int len) {
821
0
    int ret;
822
823
0
    ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
824
0
    if (ret != 0)
825
0
        return(-XML_ERR_NO_MEMORY);
826
0
    return(len);
827
0
}
828
#endif
829
830
#ifdef LIBXML_ZLIB_ENABLED
831
/************************************************************************
832
 *                  *
833
 *    I/O for compressed file accesses      *
834
 *                  *
835
 ************************************************************************/
836
837
/**
838
 * xmlGzfileRead:
839
 * @context:  the I/O context
840
 * @buffer:  where to drop data
841
 * @len:  number of bytes to write
842
 *
843
 * Read @len bytes to @buffer from the compressed I/O channel.
844
 *
845
 * Returns the number of bytes read.
846
 */
847
static int
848
xmlGzfileRead (void * context, char * buffer, int len) {
849
    int ret;
850
851
    ret = gzread((gzFile) context, &buffer[0], len);
852
    if (ret < 0)
853
        return(-XML_IO_UNKNOWN);
854
    return(ret);
855
}
856
857
#ifdef LIBXML_OUTPUT_ENABLED
858
/**
859
 * xmlGzfileWrite:
860
 * @context:  the I/O context
861
 * @buffer:  where to drop data
862
 * @len:  number of bytes to write
863
 *
864
 * Write @len bytes from @buffer to the compressed I/O channel.
865
 *
866
 * Returns the number of bytes written
867
 */
868
static int
869
xmlGzfileWrite (void * context, const char * buffer, int len) {
870
    int ret;
871
872
    ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
873
    if (ret < 0)
874
        return(-XML_IO_UNKNOWN);
875
    return(ret);
876
}
877
#endif /* LIBXML_OUTPUT_ENABLED */
878
879
/**
880
 * xmlGzfileClose:
881
 * @context:  the I/O context
882
 *
883
 * Close a compressed I/O channel
884
 */
885
static int
886
xmlGzfileClose (void * context) {
887
    if (gzclose((gzFile) context) != Z_OK)
888
        return(XML_IO_UNKNOWN);
889
    return(0);
890
}
891
#endif /* LIBXML_ZLIB_ENABLED */
892
893
/************************************************************************
894
 *                  *
895
 *    I/O for compressed file accesses      *
896
 *                  *
897
 ************************************************************************/
898
899
#ifdef LIBXML_LZMA_ENABLED
900
901
#include "private/xzlib.h"
902
903
/**
904
 * xmlXzfileRead:
905
 * @context:  the I/O context
906
 * @buffer:  where to drop data
907
 * @len:  number of bytes to write
908
 *
909
 * Read @len bytes to @buffer from the compressed I/O channel.
910
 *
911
 * Returns the number of bytes written
912
 */
913
static int
914
xmlXzfileRead (void * context, char * buffer, int len) {
915
    int ret;
916
917
    ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
918
    if (ret < 0)
919
        return(-XML_IO_UNKNOWN);
920
    return(ret);
921
}
922
923
/**
924
 * xmlXzfileClose:
925
 * @context:  the I/O context
926
 *
927
 * Close a compressed I/O channel
928
 */
929
static int
930
xmlXzfileClose (void * context) {
931
    if (__libxml2_xzclose((xzFile) context) != LZMA_OK)
932
        return(XML_IO_UNKNOWN);
933
    return(0);
934
}
935
#endif /* LIBXML_LZMA_ENABLED */
936
937
/************************************************************************
938
 *                  *
939
 *      I/O for HTTP file accesses      *
940
 *                  *
941
 ************************************************************************/
942
943
#ifdef LIBXML_HTTP_ENABLED
944
/**
945
 * xmlIOHTTPMatch:
946
 * @filename:  the URI for matching
947
 *
948
 * DEPRECATED: Internal function, don't use.
949
 *
950
 * check if the URI matches an HTTP one
951
 *
952
 * Returns 1 if matches, 0 otherwise
953
 */
954
int
955
xmlIOHTTPMatch (const char *filename) {
956
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
957
  return(1);
958
    return(0);
959
}
960
961
/**
962
 * xmlIOHTTPOpen:
963
 * @filename:  the URI for matching
964
 *
965
 * DEPRECATED: Internal function, don't use.
966
 *
967
 * open an HTTP I/O channel
968
 *
969
 * Returns an I/O context or NULL in case of error
970
 */
971
void *
972
xmlIOHTTPOpen (const char *filename) {
973
    return(xmlNanoHTTPOpen(filename, NULL));
974
}
975
976
#ifdef LIBXML_OUTPUT_ENABLED
977
/**
978
 * xmlIOHTTPOpenW:
979
 * @post_uri:  The destination URI for the document
980
 * @compression:  The compression desired for the document.
981
 *
982
 * DEPRECATED: Support for HTTP POST has been removed.
983
 *
984
 * Returns NULL.
985
 */
986
void *
987
xmlIOHTTPOpenW(const char *post_uri ATTRIBUTE_UNUSED,
988
               int compression ATTRIBUTE_UNUSED)
989
{
990
    return(NULL);
991
}
992
#endif /* LIBXML_OUTPUT_ENABLED */
993
994
/**
995
 * xmlIOHTTPRead:
996
 * @context:  the I/O context
997
 * @buffer:  where to drop data
998
 * @len:  number of bytes to write
999
 *
1000
 * DEPRECATED: Internal function, don't use.
1001
 *
1002
 * Read @len bytes to @buffer from the I/O channel.
1003
 *
1004
 * Returns the number of bytes written
1005
 */
1006
int
1007
xmlIOHTTPRead(void * context, char * buffer, int len) {
1008
    if ((buffer == NULL) || (len < 0)) return(-1);
1009
    return(xmlNanoHTTPRead(context, &buffer[0], len));
1010
}
1011
1012
/**
1013
 * xmlIOHTTPClose:
1014
 * @context:  the I/O context
1015
 *
1016
 * DEPRECATED: Internal function, don't use.
1017
 *
1018
 * Close an HTTP I/O channel
1019
 *
1020
 * Returns 0
1021
 */
1022
int
1023
xmlIOHTTPClose (void * context) {
1024
    xmlNanoHTTPClose(context);
1025
    return 0;
1026
}
1027
#endif /* LIBXML_HTTP_ENABLED */
1028
1029
/************************************************************************
1030
 *                  *
1031
 *      Input/output buffers        *
1032
 *                  *
1033
 ************************************************************************/
1034
1035
static int
1036
0
xmlIODefaultMatch(const char *filename ATTRIBUTE_UNUSED) {
1037
0
    return(1);
1038
0
}
1039
1040
/**
1041
 * xmlInputFromFd:
1042
 * @buf:  parser input buffer
1043
 * @fd:  file descriptor
1044
 * @flags:  flags
1045
 *
1046
 * Update the buffer to read from @fd. Supports the XML_INPUT_UNZIP
1047
 * flag.
1048
 *
1049
 * Returns an xmlParserErrors code.
1050
 */
1051
xmlParserErrors
1052
xmlInputFromFd(xmlParserInputBufferPtr buf, int fd,
1053
0
               xmlParserInputFlags flags) {
1054
0
    xmlFdIOCtxt *fdctxt;
1055
0
    int copy;
1056
1057
0
    (void) flags;
1058
1059
#ifdef LIBXML_LZMA_ENABLED
1060
    if (flags & XML_INPUT_UNZIP) {
1061
        xzFile xzStream;
1062
        off_t pos;
1063
1064
        pos = lseek(fd, 0, SEEK_CUR);
1065
1066
        copy = dup(fd);
1067
        if (copy == -1)
1068
            return(xmlIOErr(errno));
1069
1070
        xzStream = __libxml2_xzdopen("?", copy, "rb");
1071
1072
        if (xzStream == NULL) {
1073
            close(copy);
1074
        } else {
1075
            int compressed = (__libxml2_xzcompressed(xzStream) > 0);
1076
1077
            if ((compressed) ||
1078
                /* Try to rewind if not gzip compressed */
1079
                (pos < 0) ||
1080
                (lseek(fd, pos, SEEK_SET) < 0)) {
1081
                /*
1082
                 * If a file isn't seekable, we pipe uncompressed
1083
                 * input through xzlib.
1084
                 */
1085
                buf->context = xzStream;
1086
                buf->readcallback = xmlXzfileRead;
1087
                buf->closecallback = xmlXzfileClose;
1088
                buf->compressed = compressed;
1089
1090
                return(XML_ERR_OK);
1091
            }
1092
1093
            xmlXzfileClose(xzStream);
1094
        }
1095
    }
1096
#endif /* LIBXML_LZMA_ENABLED */
1097
1098
#ifdef LIBXML_ZLIB_ENABLED
1099
    if (flags & XML_INPUT_UNZIP) {
1100
        gzFile gzStream;
1101
        off_t pos;
1102
1103
        pos = lseek(fd, 0, SEEK_CUR);
1104
1105
        copy = dup(fd);
1106
        if (copy == -1)
1107
            return(xmlIOErr(errno));
1108
1109
        gzStream = gzdopen(copy, "rb");
1110
1111
        if (gzStream == NULL) {
1112
            close(copy);
1113
        } else {
1114
            int compressed = (gzdirect(gzStream) == 0);
1115
1116
            if ((compressed) ||
1117
                /* Try to rewind if not gzip compressed */
1118
                (pos < 0) ||
1119
                (lseek(fd, pos, SEEK_SET) < 0)) {
1120
                /*
1121
                 * If a file isn't seekable, we pipe uncompressed
1122
                 * input through zlib.
1123
                 */
1124
                buf->context = gzStream;
1125
                buf->readcallback = xmlGzfileRead;
1126
                buf->closecallback = xmlGzfileClose;
1127
                buf->compressed = compressed;
1128
1129
                return(XML_ERR_OK);
1130
            }
1131
1132
            xmlGzfileClose(gzStream);
1133
        }
1134
    }
1135
#endif /* LIBXML_ZLIB_ENABLED */
1136
1137
0
    copy = dup(fd);
1138
0
    if (copy == -1)
1139
0
        return(xmlIOErr(errno));
1140
1141
0
    fdctxt = xmlMalloc(sizeof(*fdctxt));
1142
0
    if (fdctxt == NULL) {
1143
0
        close(copy);
1144
0
        return(XML_ERR_NO_MEMORY);
1145
0
    }
1146
0
    fdctxt->fd = copy;
1147
1148
0
    buf->context = fdctxt;
1149
0
    buf->readcallback = xmlFdRead;
1150
0
    buf->closecallback = xmlFdClose;
1151
1152
0
    return(XML_ERR_OK);
1153
0
}
1154
1155
/**
1156
 * xmlInputDefaultOpen:
1157
 * @buf:  input buffer to be filled
1158
 * @filename:  filename or URI
1159
 * @flags:  XML_INPUT flags
1160
 *
1161
 * Returns an xmlParserErrors code.
1162
 */
1163
static xmlParserErrors
1164
xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename,
1165
0
                    xmlParserInputFlags flags) {
1166
0
    xmlParserErrors ret;
1167
0
    int fd;
1168
1169
#ifdef LIBXML_HTTP_ENABLED
1170
    if (xmlIOHTTPMatch(filename)) {
1171
        if ((flags & XML_INPUT_NETWORK) == 0)
1172
            return(XML_IO_NETWORK_ATTEMPT);
1173
1174
        buf->context = xmlIOHTTPOpen(filename);
1175
1176
        if (buf->context != NULL) {
1177
            buf->readcallback = xmlIOHTTPRead;
1178
            buf->closecallback = xmlIOHTTPClose;
1179
            return(XML_ERR_OK);
1180
        }
1181
    }
1182
#endif /* LIBXML_HTTP_ENABLED */
1183
1184
0
    if (!xmlFileMatch(filename))
1185
0
        return(XML_IO_ENOENT);
1186
1187
0
    ret = xmlFdOpen(filename, 0, &fd);
1188
0
    if (ret != XML_ERR_OK)
1189
0
        return(ret);
1190
1191
0
    ret = xmlInputFromFd(buf, fd, flags);
1192
1193
0
    close(fd);
1194
1195
0
    return(ret);
1196
0
}
1197
1198
#ifdef LIBXML_OUTPUT_ENABLED
1199
/**
1200
 * xmlOutputDefaultOpen:
1201
 * @buf:  input buffer to be filled
1202
 * @filename:  filename or URI
1203
 * @compression:  compression level or 0
1204
 * @is_file_uri:  whether filename is a file URI
1205
 *
1206
 * Returns an xmlParserErrors code.
1207
 */
1208
static xmlParserErrors
1209
xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename,
1210
0
                     int compression) {
1211
0
    xmlFdIOCtxt *fdctxt;
1212
0
    int fd;
1213
1214
0
    (void) compression;
1215
1216
0
    if (!strcmp(filename, "-")) {
1217
0
        fd = dup(STDOUT_FILENO);
1218
1219
0
        if (fd < 0)
1220
0
            return(xmlIOErr(errno));
1221
0
    } else {
1222
0
        int ret;
1223
1224
0
        ret = xmlFdOpen(filename, /* write */ 1, &fd);
1225
0
        if (ret != XML_ERR_OK)
1226
0
            return(ret);
1227
0
    }
1228
1229
#ifdef LIBXML_ZLIB_ENABLED
1230
    if ((compression > 0) && (compression <= 9)) {
1231
        gzFile gzStream;
1232
        char mode[15];
1233
1234
        snprintf(mode, sizeof(mode), "wb%d", compression);
1235
        gzStream = gzdopen(fd, mode);
1236
1237
        if (gzStream == NULL) {
1238
            close(fd);
1239
            return(XML_IO_UNKNOWN);
1240
        }
1241
1242
        buf->context = gzStream;
1243
        buf->writecallback = xmlGzfileWrite;
1244
        buf->closecallback = xmlGzfileClose;
1245
1246
        return(XML_ERR_OK);
1247
    }
1248
#endif /* LIBXML_ZLIB_ENABLED */
1249
1250
0
    fdctxt = xmlMalloc(sizeof(*fdctxt));
1251
0
    if (fdctxt == NULL) {
1252
0
        close(fd);
1253
0
        return(XML_ERR_NO_MEMORY);
1254
0
    }
1255
0
    fdctxt->fd = fd;
1256
1257
0
    buf->context = fdctxt;
1258
0
    buf->writecallback = xmlFdWrite;
1259
0
    buf->closecallback = xmlFdClose;
1260
0
    return(XML_ERR_OK);
1261
0
}
1262
#endif
1263
1264
/**
1265
 * xmlAllocParserInputBuffer:
1266
 * @enc:  the charset encoding if known (deprecated)
1267
 *
1268
 * DEPRECATED: Use xmlNewInputFrom*.
1269
 *
1270
 * Create a buffered parser input for progressive parsing.
1271
 *
1272
 * The encoding argument is deprecated and should be set to
1273
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1274
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1275
 *
1276
 * Returns the new parser input or NULL
1277
 */
1278
xmlParserInputBufferPtr
1279
272k
xmlAllocParserInputBuffer(xmlCharEncoding enc) {
1280
272k
    xmlParserInputBufferPtr ret;
1281
1282
272k
    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1283
272k
    if (ret == NULL) {
1284
0
  return(NULL);
1285
0
    }
1286
272k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
1287
272k
    ret->buffer = xmlBufCreate(XML_IO_BUFFER_SIZE);
1288
272k
    if (ret->buffer == NULL) {
1289
0
        xmlFree(ret);
1290
0
  return(NULL);
1291
0
    }
1292
272k
    if (enc != XML_CHAR_ENCODING_NONE) {
1293
0
        if (xmlLookupCharEncodingHandler(enc, &ret->encoder) != XML_ERR_OK) {
1294
            /* We can't handle errors properly here. */
1295
0
            xmlFreeParserInputBuffer(ret);
1296
0
            return(NULL);
1297
0
        }
1298
0
    }
1299
272k
    if (ret->encoder != NULL)
1300
0
        ret->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
1301
272k
    else
1302
272k
        ret->raw = NULL;
1303
272k
    ret->readcallback = NULL;
1304
272k
    ret->closecallback = NULL;
1305
272k
    ret->context = NULL;
1306
272k
    ret->compressed = -1;
1307
272k
    ret->rawconsumed = 0;
1308
1309
272k
    return(ret);
1310
272k
}
1311
1312
#ifdef LIBXML_OUTPUT_ENABLED
1313
/**
1314
 * xmlAllocOutputBuffer:
1315
 * @encoder:  the encoding converter or NULL
1316
 *
1317
 * Create a buffered parser output
1318
 *
1319
 * Consumes @encoder but not in error case.
1320
 *
1321
 * Returns the new parser output or NULL
1322
 */
1323
xmlOutputBufferPtr
1324
8.47k
xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
1325
8.47k
    xmlOutputBufferPtr ret;
1326
1327
8.47k
    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
1328
8.47k
    if (ret == NULL) {
1329
0
  return(NULL);
1330
0
    }
1331
8.47k
    memset(ret, 0, sizeof(xmlOutputBuffer));
1332
8.47k
    ret->buffer = xmlBufCreate(MINLEN);
1333
8.47k
    if (ret->buffer == NULL) {
1334
0
        xmlFree(ret);
1335
0
  return(NULL);
1336
0
    }
1337
1338
8.47k
    ret->encoder = encoder;
1339
8.47k
    if (encoder != NULL) {
1340
0
        ret->conv = xmlBufCreate(MINLEN);
1341
0
  if (ret->conv == NULL) {
1342
0
            xmlBufFree(ret->buffer);
1343
0
            xmlFree(ret);
1344
0
      return(NULL);
1345
0
  }
1346
1347
  /*
1348
   * This call is designed to initiate the encoder state
1349
   */
1350
0
  xmlCharEncOutput(ret, 1);
1351
0
    } else
1352
8.47k
        ret->conv = NULL;
1353
8.47k
    ret->writecallback = NULL;
1354
8.47k
    ret->closecallback = NULL;
1355
8.47k
    ret->context = NULL;
1356
8.47k
    ret->written = 0;
1357
1358
8.47k
    return(ret);
1359
8.47k
}
1360
#endif /* LIBXML_OUTPUT_ENABLED */
1361
1362
/**
1363
 * xmlFreeParserInputBuffer:
1364
 * @in:  a buffered parser input
1365
 *
1366
 * Free up the memory used by a buffered parser input
1367
 */
1368
void
1369
272k
xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1370
272k
    if (in == NULL) return;
1371
1372
272k
    if (in->raw) {
1373
2.84k
        xmlBufFree(in->raw);
1374
2.84k
  in->raw = NULL;
1375
2.84k
    }
1376
272k
    if (in->encoder != NULL) {
1377
2.84k
        xmlCharEncCloseFunc(in->encoder);
1378
2.84k
    }
1379
272k
    if (in->closecallback != NULL) {
1380
6.77k
  in->closecallback(in->context);
1381
6.77k
    }
1382
272k
    if (in->buffer != NULL) {
1383
272k
        xmlBufFree(in->buffer);
1384
272k
  in->buffer = NULL;
1385
272k
    }
1386
1387
272k
    xmlFree(in);
1388
272k
}
1389
1390
#ifdef LIBXML_OUTPUT_ENABLED
1391
/**
1392
 * xmlOutputBufferClose:
1393
 * @out:  a buffered output
1394
 *
1395
 * flushes and close the output I/O channel
1396
 * and free up all the associated resources
1397
 *
1398
 * Returns the number of byte written or a negative xmlParserErrors
1399
 * code in case of error.
1400
 */
1401
int
1402
xmlOutputBufferClose(xmlOutputBufferPtr out)
1403
8.47k
{
1404
8.47k
    int ret;
1405
1406
8.47k
    if (out == NULL)
1407
0
        return (-1);
1408
1409
8.47k
    if (out->writecallback != NULL)
1410
8.47k
        xmlOutputBufferFlush(out);
1411
1412
8.47k
    if (out->closecallback != NULL) {
1413
8.47k
        int code = out->closecallback(out->context);
1414
1415
8.47k
        if ((code != XML_ERR_OK) &&
1416
8.47k
            (!xmlIsCatastrophicError(XML_ERR_FATAL, out->error))) {
1417
0
            if (code < 0)
1418
0
                out->error = XML_IO_UNKNOWN;
1419
0
            else
1420
0
                out->error = code;
1421
0
        }
1422
8.47k
    }
1423
1424
8.47k
    if (out->error != XML_ERR_OK)
1425
0
        ret = -out->error;
1426
8.47k
    else
1427
8.47k
        ret = out->written;
1428
1429
8.47k
    if (out->conv) {
1430
0
        xmlBufFree(out->conv);
1431
0
        out->conv = NULL;
1432
0
    }
1433
8.47k
    if (out->encoder != NULL) {
1434
0
        xmlCharEncCloseFunc(out->encoder);
1435
0
    }
1436
8.47k
    if (out->buffer != NULL) {
1437
8.47k
        xmlBufFree(out->buffer);
1438
8.47k
        out->buffer = NULL;
1439
8.47k
    }
1440
1441
8.47k
    xmlFree(out);
1442
1443
8.47k
    return(ret);
1444
8.47k
}
1445
#endif /* LIBXML_OUTPUT_ENABLED */
1446
1447
/**
1448
 * xmlParserInputBufferCreateUrl:
1449
 * @URI:  the filename or URI
1450
 * @enc:  encoding enum (deprecated)
1451
 * @flags:  XML_INPUT flags
1452
 * @out:  pointer to resulting input buffer
1453
 *
1454
 * Returns an xmlParserErrors code.
1455
 */
1456
xmlParserErrors
1457
xmlParserInputBufferCreateUrl(const char *URI, xmlCharEncoding enc,
1458
                              xmlParserInputFlags flags,
1459
0
                              xmlParserInputBufferPtr *out) {
1460
0
    xmlParserInputBufferPtr buf;
1461
0
    xmlParserErrors ret;
1462
0
    int i;
1463
1464
0
    xmlInitParser();
1465
1466
0
    *out = NULL;
1467
0
    if (URI == NULL)
1468
0
        return(XML_ERR_ARGUMENT);
1469
1470
    /*
1471
     * Allocate the Input buffer front-end.
1472
     */
1473
0
    buf = xmlAllocParserInputBuffer(enc);
1474
0
    if (buf == NULL)
1475
0
        return(XML_ERR_NO_MEMORY);
1476
1477
    /*
1478
     * Try to find one of the input accept method accepting that scheme
1479
     * Go in reverse to give precedence to user defined handlers.
1480
     */
1481
0
    ret = XML_IO_ENOENT;
1482
0
    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
1483
0
        xmlInputCallback *cb = &xmlInputCallbackTable[i];
1484
1485
0
        if (cb->matchcallback == xmlIODefaultMatch) {
1486
0
            ret = xmlInputDefaultOpen(buf, URI, flags);
1487
1488
0
            if ((ret == XML_ERR_OK) || (ret != XML_IO_ENOENT))
1489
0
                break;
1490
0
        } else if ((cb->matchcallback != NULL) &&
1491
0
                   (cb->matchcallback(URI) != 0)) {
1492
0
            buf->context = cb->opencallback(URI);
1493
0
            if (buf->context != NULL) {
1494
0
                buf->readcallback = cb->readcallback;
1495
0
                buf->closecallback = cb->closecallback;
1496
0
                ret = XML_ERR_OK;
1497
0
                break;
1498
0
            }
1499
0
        }
1500
0
    }
1501
0
    if (ret != XML_ERR_OK) {
1502
0
        xmlFreeParserInputBuffer(buf);
1503
0
        *out = NULL;
1504
0
  return(ret);
1505
0
    }
1506
1507
0
    *out = buf;
1508
0
    return(ret);
1509
0
}
1510
1511
xmlParserInputBufferPtr
1512
0
__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1513
0
    xmlParserInputBufferPtr ret;
1514
1515
0
    xmlParserInputBufferCreateUrl(URI, enc, 0, &ret);
1516
0
    return(ret);
1517
0
}
1518
1519
/**
1520
 * xmlParserInputBufferCreateFilename:
1521
 * @URI:  a C string containing the URI or filename
1522
 * @enc:  the charset encoding if known
1523
 *
1524
 * DEPRECATED: Use xmlNewInputFromUrl.
1525
 *
1526
 * Create a buffered parser input for the progressive parsing of a file
1527
 * Automatic support for ZLIB/Compress compressed document is provided
1528
 * by default if found at compile-time.
1529
 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1530
 *
1531
 * Returns the new parser input or NULL
1532
 */
1533
xmlParserInputBufferPtr
1534
0
xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1535
0
    xmlParserInputBufferPtr ret;
1536
0
    xmlParserErrors code;
1537
1538
0
    if (xmlParserInputBufferCreateFilenameValue != NULL)
1539
0
        return(xmlParserInputBufferCreateFilenameValue(URI, enc));
1540
1541
0
    code = xmlParserInputBufferCreateUrl(URI, enc, 0, &ret);
1542
1543
    /*
1544
     * xmlParserInputBufferCreateFilename has no way to return
1545
     * the kind of error although it really is crucial.
1546
     * All we can do is to set the global error.
1547
     */
1548
0
    if ((code != XML_ERR_OK) && (code != XML_IO_ENOENT)) {
1549
0
        if (xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_IO, code,
1550
0
                          XML_ERR_ERROR, URI, 0, NULL, NULL, NULL, 0, 0,
1551
0
                          "Failed to open file\n") < 0)
1552
0
            xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_IO, NULL);
1553
0
    }
1554
1555
0
    return(ret);
1556
0
}
1557
1558
#ifdef LIBXML_OUTPUT_ENABLED
1559
xmlOutputBufferPtr
1560
__xmlOutputBufferCreateFilename(const char *URI,
1561
                              xmlCharEncodingHandlerPtr encoder,
1562
0
                              int compression) {
1563
0
    xmlOutputBufferPtr ret = NULL;
1564
0
    xmlURIPtr puri;
1565
0
    int i = 0;
1566
0
    char *unescaped = NULL;
1567
1568
0
    xmlInitParser();
1569
1570
0
    if (URI == NULL)
1571
0
        goto error;
1572
1573
0
    puri = xmlParseURI(URI);
1574
0
    if (puri != NULL) {
1575
        /*
1576
         * try to limit the damages of the URI unescaping code.
1577
         */
1578
0
        if (puri->scheme == NULL) {
1579
0
            unescaped = xmlURIUnescapeString(URI, 0, NULL);
1580
0
            if (unescaped == NULL) {
1581
0
                xmlFreeURI(puri);
1582
0
                goto error;
1583
0
            }
1584
0
            URI = unescaped;
1585
0
        }
1586
0
        xmlFreeURI(puri);
1587
0
    }
1588
1589
    /*
1590
     * Allocate the Output buffer front-end.
1591
     */
1592
0
    ret = xmlAllocOutputBuffer(encoder);
1593
0
    if (ret == NULL)
1594
0
        goto error;
1595
1596
    /*
1597
     * Try to find one of the output accept method accepting that scheme
1598
     * Go in reverse to give precedence to user defined handlers.
1599
     */
1600
0
    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
1601
0
        xmlOutputCallback *cb = &xmlOutputCallbackTable[i];
1602
0
        xmlParserErrors code;
1603
1604
0
        if (cb->matchcallback == xmlIODefaultMatch) {
1605
0
            code = xmlOutputDefaultOpen(ret, URI, compression);
1606
            /* TODO: Handle other errors */
1607
0
            if (code == XML_ERR_OK)
1608
0
                break;
1609
0
        } else if ((cb->matchcallback != NULL) &&
1610
0
                   (cb->matchcallback(URI) != 0)) {
1611
0
            ret->context = cb->opencallback(URI);
1612
0
            if (ret->context != NULL) {
1613
0
                ret->writecallback = cb->writecallback;
1614
0
                ret->closecallback = cb->closecallback;
1615
0
                break;
1616
0
            }
1617
0
        }
1618
0
    }
1619
1620
0
    if (ret->context == NULL) {
1621
        /* Don't free encoder */
1622
0
        ret->encoder = NULL;
1623
0
        xmlOutputBufferClose(ret);
1624
0
  ret = NULL;
1625
0
    }
1626
1627
0
error:
1628
0
    xmlFree(unescaped);
1629
0
    return(ret);
1630
0
}
1631
1632
/**
1633
 * xmlOutputBufferCreateFilename:
1634
 * @URI:  a C string containing the URI or filename
1635
 * @encoder:  the encoding converter or NULL
1636
 * @compression:  the compression ration (0 none, 9 max).
1637
 *
1638
 * Create a buffered  output for the progressive saving of a file
1639
 * If filename is "-' then we use stdout as the output.
1640
 * Automatic support for ZLIB/Compress compressed document is provided
1641
 * by default if found at compile-time.
1642
 * TODO: currently if compression is set, the library only support
1643
 *       writing to a local file.
1644
 *
1645
 * Consumes @encoder but not in error case.
1646
 *
1647
 * Returns the new output or NULL
1648
 */
1649
xmlOutputBufferPtr
1650
xmlOutputBufferCreateFilename(const char *URI,
1651
                              xmlCharEncodingHandlerPtr encoder,
1652
0
                              int compression ATTRIBUTE_UNUSED) {
1653
0
    if ((xmlOutputBufferCreateFilenameValue)) {
1654
0
    return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
1655
0
  }
1656
0
  return __xmlOutputBufferCreateFilename(URI, encoder, compression);
1657
0
}
1658
#endif /* LIBXML_OUTPUT_ENABLED */
1659
1660
/**
1661
 * xmlParserInputBufferCreateFile:
1662
 * @file:  a FILE*
1663
 * @enc:  the charset encoding if known (deprecated)
1664
 *
1665
 * DEPRECATED: Don't use.
1666
 *
1667
 * Create a buffered parser input for the progressive parsing of a FILE *
1668
 * buffered C I/O
1669
 *
1670
 * The encoding argument is deprecated and should be set to
1671
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1672
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1673
 *
1674
 * Returns the new parser input or NULL
1675
 */
1676
xmlParserInputBufferPtr
1677
0
xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
1678
0
    xmlParserInputBufferPtr ret;
1679
1680
0
    if (file == NULL) return(NULL);
1681
1682
0
    ret = xmlAllocParserInputBuffer(enc);
1683
0
    if (ret != NULL) {
1684
0
        ret->context = file;
1685
0
  ret->readcallback = xmlFileRead;
1686
0
  ret->closecallback = NULL;
1687
0
    }
1688
1689
0
    return(ret);
1690
0
}
1691
1692
#ifdef LIBXML_OUTPUT_ENABLED
1693
/**
1694
 * xmlOutputBufferCreateFile:
1695
 * @file:  a FILE*
1696
 * @encoder:  the encoding converter or NULL
1697
 *
1698
 * Create a buffered output for the progressive saving to a FILE *
1699
 * buffered C I/O
1700
 *
1701
 * Consumes @encoder but not in error case.
1702
 *
1703
 * Returns the new parser output or NULL
1704
 */
1705
xmlOutputBufferPtr
1706
0
xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
1707
0
    xmlOutputBufferPtr ret;
1708
1709
0
    if (file == NULL) {
1710
0
        return(NULL);
1711
0
    }
1712
1713
0
    ret = xmlAllocOutputBuffer(encoder);
1714
0
    if (ret != NULL) {
1715
0
        ret->context = file;
1716
0
  ret->writecallback = xmlFileWrite;
1717
0
  ret->closecallback = xmlFileFlush;
1718
0
    }
1719
1720
0
    return(ret);
1721
0
}
1722
1723
/**
1724
 * xmlOutputBufferCreateBuffer:
1725
 * @buffer:  a xmlBufferPtr
1726
 * @encoder:  the encoding converter or NULL
1727
 *
1728
 * Create a buffered output for the progressive saving to a xmlBuffer
1729
 *
1730
 * Consumes @encoder but not in error case.
1731
 *
1732
 * Returns the new parser output or NULL
1733
 */
1734
xmlOutputBufferPtr
1735
xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
1736
0
                            xmlCharEncodingHandlerPtr encoder) {
1737
0
    xmlOutputBufferPtr ret;
1738
1739
0
    if (buffer == NULL) {
1740
0
        return(NULL);
1741
0
    }
1742
1743
0
    ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
1744
0
                                  encoder);
1745
1746
0
    return(ret);
1747
0
}
1748
1749
/**
1750
 * xmlOutputBufferGetContent:
1751
 * @out:  an xmlOutputBufferPtr
1752
 *
1753
 * Gives a pointer to the data currently held in the output buffer
1754
 *
1755
 * Returns a pointer to the data or NULL in case of error
1756
 */
1757
const xmlChar *
1758
0
xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
1759
0
    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1760
0
        return(NULL);
1761
1762
0
    return(xmlBufContent(out->buffer));
1763
0
}
1764
1765
/**
1766
 * xmlOutputBufferGetSize:
1767
 * @out:  an xmlOutputBufferPtr
1768
 *
1769
 * Gives the length of the data currently held in the output buffer
1770
 *
1771
 * Returns 0 in case or error or no data is held, the size otherwise
1772
 */
1773
size_t
1774
0
xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
1775
0
    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1776
0
        return(0);
1777
1778
0
    return(xmlBufUse(out->buffer));
1779
0
}
1780
1781
1782
#endif /* LIBXML_OUTPUT_ENABLED */
1783
1784
/**
1785
 * xmlParserInputBufferCreateFd:
1786
 * @fd:  a file descriptor number
1787
 * @enc:  the charset encoding if known (deprecated)
1788
 *
1789
 * DEPRECATED: Use xmlNewInputFromFd.
1790
 *
1791
 * Create a buffered parser input for the progressive parsing for the input
1792
 * from a file descriptor
1793
 *
1794
 * The encoding argument is deprecated and should be set to
1795
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1796
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1797
 *
1798
 * Returns the new parser input or NULL
1799
 */
1800
xmlParserInputBufferPtr
1801
0
xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1802
0
    xmlParserInputBufferPtr ret;
1803
1804
0
    if (fd < 0) return(NULL);
1805
1806
0
    ret = xmlAllocParserInputBuffer(enc);
1807
0
    if (ret != NULL) {
1808
0
        xmlFdIOCtxt *fdctxt;
1809
1810
0
        fdctxt = xmlMalloc(sizeof(*fdctxt));
1811
0
        if (fdctxt == NULL) {
1812
0
            return(NULL);
1813
0
        }
1814
0
        fdctxt->fd = fd;
1815
1816
0
        ret->context = fdctxt;
1817
0
  ret->readcallback = xmlFdRead;
1818
0
        ret->closecallback = xmlFdFree;
1819
0
    }
1820
1821
0
    return(ret);
1822
0
}
1823
1824
typedef struct {
1825
    const char *cur;
1826
    size_t size;
1827
} xmlMemIOCtxt;
1828
1829
static int
1830
0
xmlMemRead(void *vctxt, char *buf, int size) {
1831
0
    xmlMemIOCtxt *ctxt = vctxt;
1832
1833
0
    if ((size_t) size > ctxt->size)
1834
0
        size = ctxt->size;
1835
1836
0
    memcpy(buf, ctxt->cur, size);
1837
0
    ctxt->cur += size;
1838
0
    ctxt->size -= size;
1839
1840
0
    return size;
1841
0
}
1842
1843
static int
1844
0
xmlMemClose(void *vctxt) {
1845
0
    xmlMemIOCtxt *ctxt = vctxt;
1846
1847
0
    xmlFree(ctxt);
1848
0
    return(0);
1849
0
}
1850
1851
/**
1852
 * xmlNewInputBufferMemory:
1853
 * @mem:  memory buffer
1854
 * @size:  size of buffer
1855
 * @flags:  flags
1856
 * @enc:  the charset encoding if known (deprecated)
1857
 *
1858
 * Create an input buffer for memory.
1859
 *
1860
 * Returns the new input buffer or NULL.
1861
 */
1862
xmlParserInputBufferPtr
1863
xmlNewInputBufferMemory(const void *mem, size_t size,
1864
0
                        xmlParserInputFlags flags, xmlCharEncoding enc) {
1865
0
    xmlParserInputBufferPtr ret;
1866
1867
0
    if ((flags & XML_INPUT_BUF_STATIC) &&
1868
0
        ((flags & XML_INPUT_BUF_ZERO_TERMINATED) == 0)) {
1869
0
        xmlMemIOCtxt *ctxt;
1870
1871
        /*
1872
         * Static buffer without zero terminator.
1873
         * Stream memory to avoid a copy.
1874
         */
1875
0
        ret = xmlAllocParserInputBuffer(enc);
1876
0
        if (ret == NULL)
1877
0
            return(NULL);
1878
1879
0
        ctxt = xmlMalloc(sizeof(*ctxt));
1880
0
        if (ctxt == NULL) {
1881
0
            xmlFreeParserInputBuffer(ret);
1882
0
            return(NULL);
1883
0
        }
1884
1885
0
        ctxt->cur = mem;
1886
0
        ctxt->size = size;
1887
1888
0
        ret->context = ctxt;
1889
0
        ret->readcallback = xmlMemRead;
1890
0
        ret->closecallback = xmlMemClose;
1891
0
    } else {
1892
0
        ret = xmlMalloc(sizeof(*ret));
1893
0
        if (ret == NULL)
1894
0
            return(NULL);
1895
0
        memset(ret, 0, sizeof(xmlParserInputBuffer));
1896
0
        ret->compressed = -1;
1897
1898
0
        ret->buffer = xmlBufCreateMem((const xmlChar *) mem, size,
1899
0
                                      (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1900
0
        if (ret->buffer == NULL) {
1901
0
            xmlFree(ret);
1902
0
            return(NULL);
1903
0
        }
1904
0
    }
1905
1906
0
    return(ret);
1907
0
}
1908
1909
/**
1910
 * xmlParserInputBufferCreateMem:
1911
 * @mem:  the memory input
1912
 * @size:  the length of the memory block
1913
 * @enc:  the charset encoding if known (deprecated)
1914
 *
1915
 * DEPRECATED: Use xmlNewInputFromMemory.
1916
 *
1917
 * Create a parser input buffer for parsing from a memory area.
1918
 *
1919
 * This function makes a copy of the whole input buffer. If you are sure
1920
 * that the contents of the buffer will remain valid until the document
1921
 * was parsed, you can avoid the copy by using
1922
 * xmlParserInputBufferCreateStatic.
1923
 *
1924
 * The encoding argument is deprecated and should be set to
1925
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1926
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1927
 *
1928
 * Returns the new parser input or NULL in case of error.
1929
 */
1930
xmlParserInputBufferPtr
1931
0
xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
1932
0
    if ((mem == NULL) || (size < 0))
1933
0
        return(NULL);
1934
1935
0
    return(xmlNewInputBufferMemory(mem, size, 0, enc));
1936
0
}
1937
1938
/**
1939
 * xmlParserInputBufferCreateStatic:
1940
 * @mem:  the memory input
1941
 * @size:  the length of the memory block
1942
 * @enc:  the charset encoding if known
1943
 *
1944
 * DEPRECATED: Use xmlNewInputFromMemory.
1945
 *
1946
 * Create a parser input buffer for parsing from a memory area.
1947
 *
1948
 * This functions assumes that the contents of the input buffer remain
1949
 * valid until the document was parsed. Use xmlParserInputBufferCreateMem
1950
 * otherwise.
1951
 *
1952
 * The encoding argument is deprecated and should be set to
1953
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1954
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1955
 *
1956
 * Returns the new parser input or NULL in case of error.
1957
 */
1958
xmlParserInputBufferPtr
1959
xmlParserInputBufferCreateStatic(const char *mem, int size,
1960
0
                                 xmlCharEncoding enc) {
1961
0
    if ((mem == NULL) || (size < 0))
1962
0
        return(NULL);
1963
1964
0
    return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
1965
0
}
1966
1967
/**
1968
 * xmlNewInputBufferString:
1969
 * @str:  C string
1970
 * @flags:  flags
1971
 *
1972
 * DEPRECATED: Use xmlNewInputFromString.
1973
 *
1974
 * Create an input buffer for a null-terminated C string.
1975
 *
1976
 * Returns the new input buffer or NULL.
1977
 */
1978
xmlParserInputBufferPtr
1979
0
xmlNewInputBufferString(const char *str, xmlParserInputFlags flags) {
1980
0
    xmlParserInputBufferPtr ret;
1981
1982
0
    ret = xmlMalloc(sizeof(*ret));
1983
0
    if (ret == NULL)
1984
0
  return(NULL);
1985
0
    memset(ret, 0, sizeof(xmlParserInputBuffer));
1986
0
    ret->compressed = -1;
1987
1988
0
    ret->buffer = xmlBufCreateMem((const xmlChar *) str, strlen(str),
1989
0
                                  (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1990
0
    if (ret->buffer == NULL) {
1991
0
        xmlFree(ret);
1992
0
  return(NULL);
1993
0
    }
1994
1995
0
    return(ret);
1996
0
}
1997
1998
#ifdef LIBXML_OUTPUT_ENABLED
1999
/**
2000
 * xmlOutputBufferCreateFd:
2001
 * @fd:  a file descriptor number
2002
 * @encoder:  the encoding converter or NULL
2003
 *
2004
 * Create a buffered output for the progressive saving
2005
 * to a file descriptor
2006
 *
2007
 * Consumes @encoder but not in error case.
2008
 *
2009
 * Returns the new parser output or NULL
2010
 */
2011
xmlOutputBufferPtr
2012
0
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
2013
0
    xmlOutputBufferPtr ret;
2014
2015
0
    if (fd < 0) {
2016
0
        return(NULL);
2017
0
    }
2018
2019
0
    ret = xmlAllocOutputBuffer(encoder);
2020
0
    if (ret != NULL) {
2021
0
        xmlFdIOCtxt *fdctxt;
2022
2023
0
        fdctxt = xmlMalloc(sizeof(*fdctxt));
2024
0
        if (fdctxt == NULL) {
2025
0
            return(NULL);
2026
0
        }
2027
0
        fdctxt->fd = fd;
2028
2029
0
        ret->context = fdctxt;
2030
0
  ret->writecallback = xmlFdWrite;
2031
0
        ret->closecallback = xmlFdFree;
2032
0
    }
2033
2034
0
    return(ret);
2035
0
}
2036
#endif /* LIBXML_OUTPUT_ENABLED */
2037
2038
/**
2039
 * xmlParserInputBufferCreateIO:
2040
 * @ioread:  an I/O read function
2041
 * @ioclose:  an I/O close function
2042
 * @ioctx:  an I/O handler
2043
 * @enc:  the charset encoding if known (deprecated)
2044
 *
2045
 * DEPRECATED: Use xmlNewInputFromIO.
2046
 *
2047
 * Create a buffered parser input for the progressive parsing for the input
2048
 * from an I/O handler
2049
 *
2050
 * The encoding argument is deprecated and should be set to
2051
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
2052
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
2053
 *
2054
 * Returns the new parser input or NULL
2055
 */
2056
xmlParserInputBufferPtr
2057
xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
2058
0
   xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
2059
0
    xmlParserInputBufferPtr ret;
2060
2061
0
    if (ioread == NULL) return(NULL);
2062
2063
0
    ret = xmlAllocParserInputBuffer(enc);
2064
0
    if (ret != NULL) {
2065
0
        ret->context = (void *) ioctx;
2066
0
  ret->readcallback = ioread;
2067
0
  ret->closecallback = ioclose;
2068
0
    }
2069
2070
0
    return(ret);
2071
0
}
2072
2073
#ifdef LIBXML_OUTPUT_ENABLED
2074
/**
2075
 * xmlOutputBufferCreateIO:
2076
 * @iowrite:  an I/O write function
2077
 * @ioclose:  an I/O close function
2078
 * @ioctx:  an I/O handler
2079
 * @encoder:  the charset encoding if known
2080
 *
2081
 * Create a buffered output for the progressive saving
2082
 * to an I/O handler
2083
 *
2084
 * Consumes @encoder but not in error case.
2085
 *
2086
 * Returns the new parser output or NULL
2087
 */
2088
xmlOutputBufferPtr
2089
xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
2090
   xmlOutputCloseCallback  ioclose, void *ioctx,
2091
8.47k
   xmlCharEncodingHandlerPtr encoder) {
2092
8.47k
    xmlOutputBufferPtr ret;
2093
2094
8.47k
    if (iowrite == NULL) {
2095
0
        return(NULL);
2096
0
    }
2097
2098
8.47k
    ret = xmlAllocOutputBuffer(encoder);
2099
8.47k
    if (ret != NULL) {
2100
8.47k
        ret->context = (void *) ioctx;
2101
8.47k
  ret->writecallback = iowrite;
2102
8.47k
  ret->closecallback = ioclose;
2103
8.47k
    }
2104
2105
8.47k
    return(ret);
2106
8.47k
}
2107
#endif /* LIBXML_OUTPUT_ENABLED */
2108
2109
/**
2110
 * xmlParserInputBufferCreateFilenameDefault:
2111
 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
2112
 *
2113
 * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions.
2114
 *
2115
 * Registers a callback for URI input file handling
2116
 *
2117
 * Returns the old value of the registration function
2118
 */
2119
xmlParserInputBufferCreateFilenameFunc
2120
xmlParserInputBufferCreateFilenameDefault(
2121
        xmlParserInputBufferCreateFilenameFunc func)
2122
0
{
2123
0
    xmlParserInputBufferCreateFilenameFunc old;
2124
2125
0
    old = xmlParserInputBufferCreateFilenameValue;
2126
0
    if (old == NULL)
2127
0
        old = __xmlParserInputBufferCreateFilename;
2128
2129
0
    if (func == __xmlParserInputBufferCreateFilename)
2130
0
        func = NULL;
2131
0
    xmlParserInputBufferCreateFilenameValue = func;
2132
0
    return(old);
2133
0
}
2134
2135
/**
2136
 * xmlOutputBufferCreateFilenameDefault:
2137
 * @func: function pointer to the new OutputBufferCreateFilenameFunc
2138
 *
2139
 * Registers a callback for URI output file handling
2140
 *
2141
 * Returns the old value of the registration function
2142
 */
2143
xmlOutputBufferCreateFilenameFunc
2144
xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
2145
0
{
2146
0
    xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
2147
0
#ifdef LIBXML_OUTPUT_ENABLED
2148
0
    if (old == NULL) {
2149
0
    old = __xmlOutputBufferCreateFilename;
2150
0
  }
2151
0
#endif
2152
0
    xmlOutputBufferCreateFilenameValue = func;
2153
0
    return(old);
2154
0
}
2155
2156
/**
2157
 * xmlParserInputBufferPush:
2158
 * @in:  a buffered parser input
2159
 * @len:  the size in bytes of the array.
2160
 * @buf:  an char array
2161
 *
2162
 * DEPRECATED: Internal function, don't use.
2163
 *
2164
 * Push the content of the arry in the input buffer
2165
 * This routine handle the I18N transcoding to internal UTF-8
2166
 * This is used when operating the parser in progressive (push) mode.
2167
 *
2168
 * Returns the number of chars read and stored in the buffer, or -1
2169
 *         in case of error.
2170
 */
2171
int
2172
xmlParserInputBufferPush(xmlParserInputBufferPtr in,
2173
557k
                   int len, const char *buf) {
2174
557k
    size_t nbchars = 0;
2175
557k
    int ret;
2176
2177
557k
    if (len < 0) return(0);
2178
557k
    if ((in == NULL) || (in->error)) return(-1);
2179
557k
    if (in->encoder != NULL) {
2180
        /*
2181
   * Store the data in the incoming raw buffer
2182
   */
2183
544
        if (in->raw == NULL) {
2184
0
      in->raw = xmlBufCreate(50);
2185
0
            if (in->raw == NULL) {
2186
0
                in->error = XML_ERR_NO_MEMORY;
2187
0
                return(-1);
2188
0
            }
2189
0
  }
2190
544
  ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
2191
544
  if (ret != 0) {
2192
0
            in->error = XML_ERR_NO_MEMORY;
2193
0
      return(-1);
2194
0
        }
2195
2196
  /*
2197
   * convert as much as possible to the parser reading buffer.
2198
   */
2199
544
        nbchars = SIZE_MAX;
2200
544
  if (xmlCharEncInput(in, &nbchars, /* flush */ 0) !=
2201
544
            XML_ENC_ERR_SUCCESS)
2202
4
            return(-1);
2203
540
        if (nbchars > INT_MAX)
2204
0
            nbchars = INT_MAX;
2205
557k
    } else {
2206
557k
  nbchars = len;
2207
557k
        ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
2208
557k
  if (ret != 0) {
2209
0
            in->error = XML_ERR_NO_MEMORY;
2210
0
      return(-1);
2211
0
        }
2212
557k
    }
2213
557k
    return(nbchars);
2214
557k
}
2215
2216
/**
2217
 * endOfInput:
2218
 *
2219
 * When reading from an Input channel indicated end of file or error
2220
 * don't reread from it again.
2221
 */
2222
static int
2223
endOfInput (void * context ATTRIBUTE_UNUSED,
2224
      char * buffer ATTRIBUTE_UNUSED,
2225
446k
      int len ATTRIBUTE_UNUSED) {
2226
446k
    return(0);
2227
446k
}
2228
2229
/**
2230
 * xmlParserInputBufferGrow:
2231
 * @in:  a buffered parser input
2232
 * @len:  indicative value of the amount of chars to read
2233
 *
2234
 * DEPRECATED: Internal function, don't use.
2235
 *
2236
 * Grow up the content of the input buffer, the old data are preserved
2237
 * This routine handle the I18N transcoding to internal UTF-8
2238
 * This routine is used when operating the parser in normal (pull) mode
2239
 *
2240
 * Returns the number of chars read and stored in the buffer, or -1
2241
 *         in case of error.
2242
 */
2243
int
2244
467k
xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
2245
467k
    int res = 0;
2246
2247
467k
    if ((in == NULL) || (in->error))
2248
0
        return(-1);
2249
2250
467k
    if (len < MINLEN)
2251
467k
        len = MINLEN;
2252
2253
    /*
2254
     * Call the read method for this I/O type.
2255
     */
2256
467k
    if (in->readcallback != NULL) {
2257
467k
        xmlBufPtr buf;
2258
2259
467k
        if (in->encoder == NULL) {
2260
467k
            buf = in->buffer;
2261
467k
        } else {
2262
            /*
2263
             * Some users only set 'encoder' and expect us to create
2264
             * the raw buffer lazily.
2265
             */
2266
0
            if (in->raw == NULL) {
2267
0
                in->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
2268
0
                if (in->raw == NULL) {
2269
0
                    in->error = XML_ERR_NO_MEMORY;
2270
0
                    return(-1);
2271
0
                }
2272
0
            }
2273
0
            buf = in->raw;
2274
0
        }
2275
2276
467k
        if (xmlBufGrow(buf, len) < 0) {
2277
0
            in->error = XML_ERR_NO_MEMORY;
2278
0
            return(-1);
2279
0
        }
2280
2281
467k
  res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
2282
467k
  if (res <= 0)
2283
453k
      in->readcallback = endOfInput;
2284
467k
        if (res < 0) {
2285
232
            if (res == -1)
2286
232
                in->error = XML_IO_UNKNOWN;
2287
0
            else
2288
0
                in->error = -res;
2289
232
            return(-1);
2290
232
        }
2291
2292
467k
        if (xmlBufAddLen(buf, res) < 0) {
2293
0
            in->error = XML_ERR_NO_MEMORY;
2294
0
            return(-1);
2295
0
        }
2296
467k
    }
2297
2298
    /*
2299
     * Handle encoding.
2300
     */
2301
467k
    if (in->encoder != NULL) {
2302
0
        size_t sizeOut;
2303
2304
        /*
2305
         * Don't convert whole buffer when reading from memory.
2306
         */
2307
0
        if (in->readcallback == NULL)
2308
0
            sizeOut = len;
2309
0
        else
2310
0
            sizeOut = SIZE_MAX;
2311
2312
0
  if (xmlCharEncInput(in, &sizeOut, /* flush */ 0) !=
2313
0
            XML_ENC_ERR_SUCCESS)
2314
0
      return(-1);
2315
0
        res = sizeOut;
2316
0
    }
2317
467k
    return(res);
2318
467k
}
2319
2320
/**
2321
 * xmlParserInputBufferRead:
2322
 * @in:  a buffered parser input
2323
 * @len:  indicative value of the amount of chars to read
2324
 *
2325
 * DEPRECATED: Internal function, don't use.
2326
 *
2327
 * Same as xmlParserInputBufferGrow.
2328
 *
2329
 * Returns the number of chars read and stored in the buffer, or -1
2330
 *         in case of error.
2331
 */
2332
int
2333
0
xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
2334
0
    return(xmlParserInputBufferGrow(in, len));
2335
0
}
2336
2337
#ifdef LIBXML_OUTPUT_ENABLED
2338
/**
2339
 * xmlOutputBufferWrite:
2340
 * @out:  a buffered parser output
2341
 * @len:  the size in bytes of the array.
2342
 * @data:  an char array
2343
 *
2344
 * Write the content of the array in the output I/O buffer
2345
 * This routine handle the I18N transcoding from internal UTF-8
2346
 * The buffer is lossless, i.e. will store in case of partial
2347
 * or delayed writes.
2348
 *
2349
 * Returns the number of chars immediately written, or -1
2350
 *         in case of error.
2351
 */
2352
int
2353
1.28M
xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *data) {
2354
1.28M
    xmlBufPtr buf = NULL;
2355
1.28M
    size_t written = 0;
2356
1.28M
    int ret;
2357
2358
1.28M
    if ((out == NULL) || (out->error))
2359
0
        return(-1);
2360
1.28M
    if (len < 0)
2361
0
        return(0);
2362
2363
1.28M
    ret = xmlBufAdd(out->buffer, (const xmlChar *) data, len);
2364
1.28M
    if (ret != 0) {
2365
0
        out->error = XML_ERR_NO_MEMORY;
2366
0
        return(-1);
2367
0
    }
2368
2369
    /*
2370
     * first handle encoding stuff.
2371
     */
2372
1.28M
    if (out->encoder != NULL) {
2373
        /*
2374
         * Store the data in the incoming raw buffer
2375
         */
2376
0
        if (out->conv == NULL) {
2377
0
            out->conv = xmlBufCreate(MINLEN);
2378
0
            if (out->conv == NULL) {
2379
0
                out->error = XML_ERR_NO_MEMORY;
2380
0
                return(-1);
2381
0
            }
2382
0
        }
2383
2384
        /*
2385
         * convert as much as possible to the parser reading buffer.
2386
         */
2387
0
        if (xmlBufUse(out->buffer) < 256) {
2388
0
            ret = 0;
2389
0
        } else {
2390
0
            ret = xmlCharEncOutput(out, 0);
2391
0
            if (ret < 0)
2392
0
                return(-1);
2393
0
        }
2394
2395
0
        if (out->writecallback)
2396
0
            buf = out->conv;
2397
0
        else
2398
0
            written = ret;
2399
1.28M
    } else {
2400
1.28M
        if (out->writecallback)
2401
1.28M
            buf = out->buffer;
2402
0
        else
2403
0
            written = len;
2404
1.28M
    }
2405
2406
1.28M
    if ((buf != NULL) && (out->writecallback)) {
2407
        /*
2408
         * second write the stuff to the I/O channel
2409
         */
2410
1.28M
        while (1) {
2411
1.28M
            size_t nbchars = xmlBufUse(buf);
2412
2413
1.28M
            if (nbchars < MINLEN)
2414
1.28M
                break;
2415
2416
0
            ret = out->writecallback(out->context,
2417
0
                       (const char *)xmlBufContent(buf), nbchars);
2418
0
            if (ret < 0) {
2419
0
                out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2420
0
                return(-1);
2421
0
            }
2422
0
            if ((ret == 0) || ((size_t) ret > nbchars)) {
2423
0
                out->error = XML_ERR_INTERNAL_ERROR;
2424
0
                return(-1);
2425
0
            }
2426
2427
0
            xmlBufShrink(buf, ret);
2428
0
            written += ret;
2429
0
            if (out->written > INT_MAX - ret)
2430
0
                out->written = INT_MAX;
2431
0
            else
2432
0
                out->written += ret;
2433
0
        }
2434
1.28M
    }
2435
2436
1.28M
    return(written <= INT_MAX ? written : INT_MAX);
2437
1.28M
}
2438
2439
/**
2440
 * xmlOutputBufferWriteEscape:
2441
 * @out:  a buffered parser output
2442
 * @str:  a zero terminated UTF-8 string
2443
 * @escaping:  an optional escaping function (or NULL)
2444
 *
2445
 * Write the content of the string in the output I/O buffer
2446
 * This routine escapes the characters and then handle the I18N
2447
 * transcoding from internal UTF-8
2448
 * The buffer is lossless, i.e. will store in case of partial
2449
 * or delayed writes.
2450
 *
2451
 * Returns the number of chars immediately written, or -1
2452
 *         in case of error.
2453
 */
2454
int
2455
xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
2456
0
                           xmlCharEncodingOutputFunc escaping) {
2457
0
    int ret;
2458
0
    int written = 0;
2459
0
    size_t len;
2460
2461
0
    if ((out == NULL) || (out->error) || (str == NULL))
2462
0
        return(-1);
2463
2464
0
    len = strlen((const char *) str);
2465
0
    if (len >= INT_MAX) {
2466
0
        out->error = XML_ERR_RESOURCE_LIMIT;
2467
0
        return(-1);
2468
0
    }
2469
2470
0
    if (escaping == NULL) {
2471
0
        char *escaped = (char *) xmlEscapeText(str, XML_ESCAPE_ALLOW_INVALID);
2472
2473
0
        if (escaped == NULL) {
2474
0
            out->error = XML_ERR_NO_MEMORY;
2475
0
            return(-1);
2476
0
        }
2477
2478
0
        len = strlen(escaped);
2479
0
        if (len >= INT_MAX) {
2480
0
            out->error = XML_ERR_RESOURCE_LIMIT;
2481
0
            return(-1);
2482
0
        }
2483
2484
0
        ret = xmlOutputBufferWrite(out, len, escaped);
2485
2486
0
        xmlFree(escaped);
2487
0
        return(ret);
2488
0
    }
2489
2490
0
    while (len > 0) {
2491
0
        xmlChar buf[1024];
2492
0
        int c_out;
2493
0
        int c_in;
2494
2495
0
  c_out = 1024;
2496
0
  c_in = len;
2497
2498
0
        ret = escaping(buf, &c_out, str, &c_in);
2499
0
        if (ret < 0) {
2500
0
            out->error = XML_ERR_NO_MEMORY;
2501
0
            return(-1);
2502
0
        }
2503
0
        str += c_in;
2504
0
        len -= c_in;
2505
2506
0
        ret = xmlOutputBufferWrite(out, c_out, (char *) buf);
2507
0
        if (ret < 0)
2508
0
            return(ret);
2509
0
        written += ret;
2510
0
    }
2511
2512
0
    return(written);
2513
0
}
2514
2515
/**
2516
 * xmlOutputBufferWriteString:
2517
 * @out:  a buffered parser output
2518
 * @str:  a zero terminated C string
2519
 *
2520
 * Write the content of the string in the output I/O buffer
2521
 * This routine handle the I18N transcoding from internal UTF-8
2522
 * The buffer is lossless, i.e. will store in case of partial
2523
 * or delayed writes.
2524
 *
2525
 * Returns the number of chars immediately written, or -1
2526
 *         in case of error.
2527
 */
2528
int
2529
1.09M
xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
2530
1.09M
    int len;
2531
2532
1.09M
    if ((out == NULL) || (out->error)) return(-1);
2533
1.09M
    if (str == NULL)
2534
0
        return(-1);
2535
1.09M
    len = strlen(str);
2536
2537
1.09M
    if (len > 0)
2538
1.09M
  return(xmlOutputBufferWrite(out, len, str));
2539
0
    return(len);
2540
1.09M
}
2541
2542
/**
2543
 * xmlOutputBufferWriteQuotedString:
2544
 * @buf:  output buffer
2545
 * @string:  the string to add
2546
 *
2547
 * routine which manage and grows an output buffer. This one writes
2548
 * a quoted or double quoted #xmlChar string, checking first if it holds
2549
 * quote or double-quotes internally
2550
 */
2551
void
2552
xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,
2553
0
                                 const xmlChar *string) {
2554
0
    const xmlChar *cur, *base;
2555
2556
0
    if ((buf == NULL) || (buf->error))
2557
0
        return;
2558
2559
0
    if (xmlStrchr(string, '\"')) {
2560
0
        if (xmlStrchr(string, '\'')) {
2561
0
      xmlOutputBufferWrite(buf, 1, "\"");
2562
0
            base = cur = string;
2563
0
            while(*cur != 0){
2564
0
                if(*cur == '"'){
2565
0
                    if (base != cur)
2566
0
                        xmlOutputBufferWrite(buf, cur - base,
2567
0
                                             (const char *) base);
2568
0
                    xmlOutputBufferWrite(buf, 6, "&quot;");
2569
0
                    cur++;
2570
0
                    base = cur;
2571
0
                }
2572
0
                else {
2573
0
                    cur++;
2574
0
                }
2575
0
            }
2576
0
            if (base != cur)
2577
0
                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
2578
0
      xmlOutputBufferWrite(buf, 1, "\"");
2579
0
  }
2580
0
        else{
2581
0
      xmlOutputBufferWrite(buf, 1, "'");
2582
0
            xmlOutputBufferWriteString(buf, (const char *) string);
2583
0
      xmlOutputBufferWrite(buf, 1, "'");
2584
0
        }
2585
0
    } else {
2586
0
        xmlOutputBufferWrite(buf, 1, "\"");
2587
0
        xmlOutputBufferWriteString(buf, (const char *) string);
2588
0
        xmlOutputBufferWrite(buf, 1, "\"");
2589
0
    }
2590
0
}
2591
2592
/**
2593
 * xmlOutputBufferFlush:
2594
 * @out:  a buffered output
2595
 *
2596
 * flushes the output I/O channel
2597
 *
2598
 * Returns the number of byte written or -1 in case of error.
2599
 */
2600
int
2601
8.47k
xmlOutputBufferFlush(xmlOutputBufferPtr out) {
2602
8.47k
    int nbchars = 0, ret = 0;
2603
2604
8.47k
    if ((out == NULL) || (out->error)) return(-1);
2605
    /*
2606
     * first handle encoding stuff.
2607
     */
2608
8.47k
    if ((out->conv != NULL) && (out->encoder != NULL)) {
2609
  /*
2610
   * convert as much as possible to the parser output buffer.
2611
   */
2612
0
  do {
2613
0
      nbchars = xmlCharEncOutput(out, 0);
2614
0
      if (nbchars < 0)
2615
0
    return(-1);
2616
0
  } while (nbchars);
2617
0
    }
2618
2619
    /*
2620
     * second flush the stuff to the I/O channel
2621
     */
2622
8.47k
    if ((out->conv != NULL) && (out->encoder != NULL) &&
2623
8.47k
  (out->writecallback != NULL)) {
2624
0
  ret = out->writecallback(out->context,
2625
0
                                 (const char *)xmlBufContent(out->conv),
2626
0
                                 xmlBufUse(out->conv));
2627
0
  if (ret >= 0)
2628
0
      xmlBufShrink(out->conv, ret);
2629
8.47k
    } else if (out->writecallback != NULL) {
2630
8.47k
  ret = out->writecallback(out->context,
2631
8.47k
                                 (const char *)xmlBufContent(out->buffer),
2632
8.47k
                                 xmlBufUse(out->buffer));
2633
8.47k
  if (ret >= 0)
2634
8.47k
      xmlBufShrink(out->buffer, ret);
2635
8.47k
    }
2636
8.47k
    if (ret < 0) {
2637
0
        out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2638
0
  return(ret);
2639
0
    }
2640
8.47k
    if (out->written > INT_MAX - ret)
2641
0
        out->written = INT_MAX;
2642
8.47k
    else
2643
8.47k
        out->written += ret;
2644
2645
8.47k
    return(ret);
2646
8.47k
}
2647
#endif /* LIBXML_OUTPUT_ENABLED */
2648
2649
/**
2650
 * xmlParserGetDirectory:
2651
 * @filename:  the path to a file
2652
 *
2653
 * lookup the directory for that file
2654
 *
2655
 * Returns a new allocated string containing the directory, or NULL.
2656
 */
2657
char *
2658
0
xmlParserGetDirectory(const char *filename) {
2659
0
    char *ret = NULL;
2660
0
    char dir[1024];
2661
0
    char *cur;
2662
2663
0
    if (filename == NULL) return(NULL);
2664
2665
#if defined(_WIN32)
2666
#   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
2667
#else
2668
0
#   define IS_XMLPGD_SEP(ch) (ch=='/')
2669
0
#endif
2670
2671
0
    strncpy(dir, filename, 1023);
2672
0
    dir[1023] = 0;
2673
0
    cur = &dir[strlen(dir)];
2674
0
    while (cur > dir) {
2675
0
         if (IS_XMLPGD_SEP(*cur)) break;
2676
0
   cur --;
2677
0
    }
2678
0
    if (IS_XMLPGD_SEP(*cur)) {
2679
0
        if (cur == dir) dir[1] = 0;
2680
0
  else *cur = 0;
2681
0
  ret = xmlMemStrdup(dir);
2682
0
    } else {
2683
0
        ret = xmlMemStrdup(".");
2684
0
    }
2685
0
    return(ret);
2686
0
#undef IS_XMLPGD_SEP
2687
0
}
2688
2689
/**
2690
 * xmlNoNetExists:
2691
 * @filename:  the path to check
2692
 *
2693
 * DEPRECATED: Internal function, don't use.
2694
 *
2695
 * Like xmlCheckFilename but handles file URIs.
2696
 *
2697
 * Returns 0, 1, or 2.
2698
 */
2699
int
2700
0
xmlNoNetExists(const char *filename) {
2701
0
    char *fromUri;
2702
0
    int ret;
2703
2704
0
    if (filename == NULL)
2705
0
  return(0);
2706
2707
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
2708
0
        return(0);
2709
2710
0
    if (fromUri != NULL)
2711
0
        filename = fromUri;
2712
2713
0
    ret =  xmlCheckFilename(filename);
2714
2715
0
    xmlFree(fromUri);
2716
0
    return(ret);
2717
0
}
2718
2719
/************************************************************************
2720
 *                  *
2721
 *      Input/output callbacks        *
2722
 *                  *
2723
 ************************************************************************/
2724
2725
/**
2726
 * xmlInitIOCallbacks:
2727
 *
2728
 * Initialize callback tables.
2729
 */
2730
void
2731
xmlInitIOCallbacks(void)
2732
18
{
2733
18
    xmlInputCallbackNr = 1;
2734
18
    xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2735
2736
18
#ifdef LIBXML_OUTPUT_ENABLED
2737
18
    xmlOutputCallbackNr = 1;
2738
18
    xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2739
18
#endif
2740
18
}
2741
2742
/**
2743
 * xmlRegisterInputCallbacks:
2744
 * @matchFunc:  the xmlInputMatchCallback
2745
 * @openFunc:  the xmlInputOpenCallback
2746
 * @readFunc:  the xmlInputReadCallback
2747
 * @closeFunc:  the xmlInputCloseCallback
2748
 *
2749
 * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions.
2750
 *
2751
 * Register a new set of I/O callback for handling parser input.
2752
 *
2753
 * Returns the registered handler number or -1 in case of error
2754
 */
2755
int
2756
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2757
  xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2758
0
  xmlInputCloseCallback closeFunc) {
2759
0
    xmlInitParser();
2760
2761
0
    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2762
0
  return(-1);
2763
0
    }
2764
0
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2765
0
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2766
0
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2767
0
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2768
0
    return(xmlInputCallbackNr++);
2769
0
}
2770
2771
/**
2772
 * xmlRegisterDefaultInputCallbacks:
2773
 *
2774
 * Registers the default compiled-in I/O handlers.
2775
 */
2776
void
2777
0
xmlRegisterDefaultInputCallbacks(void) {
2778
0
    xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2779
0
}
2780
2781
/**
2782
 * xmlPopInputCallbacks:
2783
 *
2784
 * Clear the top input callback from the input stack. this includes the
2785
 * compiled-in I/O.
2786
 *
2787
 * Returns the number of input callback registered or -1 in case of error.
2788
 */
2789
int
2790
xmlPopInputCallbacks(void)
2791
0
{
2792
0
    xmlInitParser();
2793
2794
0
    if (xmlInputCallbackNr <= 0)
2795
0
        return(-1);
2796
2797
0
    xmlInputCallbackNr--;
2798
2799
0
    return(xmlInputCallbackNr);
2800
0
}
2801
2802
/**
2803
 * xmlCleanupInputCallbacks:
2804
 *
2805
 * clears the entire input callback table. this includes the
2806
 * compiled-in I/O.
2807
 */
2808
void
2809
xmlCleanupInputCallbacks(void)
2810
0
{
2811
0
    xmlInitParser();
2812
2813
0
    xmlInputCallbackNr = 0;
2814
0
}
2815
2816
#ifdef LIBXML_OUTPUT_ENABLED
2817
/**
2818
 * xmlRegisterOutputCallbacks:
2819
 * @matchFunc:  the xmlOutputMatchCallback
2820
 * @openFunc:  the xmlOutputOpenCallback
2821
 * @writeFunc:  the xmlOutputWriteCallback
2822
 * @closeFunc:  the xmlOutputCloseCallback
2823
 *
2824
 * Register a new set of I/O callback for handling output.
2825
 *
2826
 * Returns the registered handler number or -1 in case of error
2827
 */
2828
int
2829
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2830
  xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2831
0
  xmlOutputCloseCallback closeFunc) {
2832
0
    xmlInitParser();
2833
2834
0
    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2835
0
  return(-1);
2836
0
    }
2837
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2838
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2839
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2840
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2841
0
    return(xmlOutputCallbackNr++);
2842
0
}
2843
2844
/**
2845
 * xmlRegisterDefaultOutputCallbacks:
2846
 *
2847
 * Registers the default compiled-in I/O handlers.
2848
 */
2849
void
2850
0
xmlRegisterDefaultOutputCallbacks (void) {
2851
0
    xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2852
0
}
2853
2854
/**
2855
 * xmlPopOutputCallbacks:
2856
 *
2857
 * Remove the top output callbacks from the output stack. This includes the
2858
 * compiled-in I/O.
2859
 *
2860
 * Returns the number of output callback registered or -1 in case of error.
2861
 */
2862
int
2863
xmlPopOutputCallbacks(void)
2864
0
{
2865
0
    xmlInitParser();
2866
2867
0
    if (xmlOutputCallbackNr <= 0)
2868
0
        return(-1);
2869
2870
0
    xmlOutputCallbackNr--;
2871
2872
0
    return(xmlOutputCallbackNr);
2873
0
}
2874
2875
/**
2876
 * xmlCleanupOutputCallbacks:
2877
 *
2878
 * clears the entire output callback table. this includes the
2879
 * compiled-in I/O callbacks.
2880
 */
2881
void
2882
xmlCleanupOutputCallbacks(void)
2883
0
{
2884
0
    xmlInitParser();
2885
2886
0
    xmlOutputCallbackNr = 0;
2887
0
}
2888
2889
#ifdef LIBXML_HTTP_ENABLED
2890
/**
2891
 * xmlRegisterHTTPPostCallbacks:
2892
 *
2893
 * DEPRECATED: Support for HTTP POST has been removed.
2894
 */
2895
void
2896
xmlRegisterHTTPPostCallbacks(void) {
2897
    xmlRegisterDefaultOutputCallbacks();
2898
}
2899
#endif
2900
#endif /* LIBXML_OUTPUT_ENABLED */
2901