Coverage Report

Created: 2025-10-28 07:11

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