Coverage Report

Created: 2025-12-30 06:58

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
411k
#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
61.3k
xmlFreeParserInputBuffer(xmlParserInputBuffer *in) {
1412
61.3k
    if (in == NULL) return;
1413
1414
61.3k
    if (in->raw) {
1415
2.30k
        xmlBufFree(in->raw);
1416
2.30k
  in->raw = NULL;
1417
2.30k
    }
1418
61.3k
    if (in->encoder != NULL) {
1419
2.30k
        xmlCharEncCloseFunc(in->encoder);
1420
2.30k
    }
1421
61.3k
    if (in->closecallback != NULL) {
1422
0
  in->closecallback(in->context);
1423
0
    }
1424
61.3k
    if (in->buffer != NULL) {
1425
61.3k
        xmlBufFree(in->buffer);
1426
61.3k
  in->buffer = NULL;
1427
61.3k
    }
1428
1429
61.3k
    xmlFree(in);
1430
61.3k
}
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->encoder != NULL) && (out->conv == NULL)) || (out->error != 0))
1828
0
        return(NULL);
1829
1830
0
    if (out->encoder != NULL)
1831
0
        return(xmlBufContent(out->conv));
1832
1833
0
    return(xmlBufContent(out->buffer));
1834
0
}
1835
1836
/**
1837
 * Gives the length of the data currently held in the output buffer
1838
 *
1839
 * @param out  an xmlOutputBuffer
1840
 * @returns 0 in case or error or no data is held, the size otherwise
1841
 */
1842
size_t
1843
0
xmlOutputBufferGetSize(xmlOutputBuffer *out) {
1844
0
    if ((out == NULL) || (out->buffer == NULL) || ((out->encoder != NULL) && (out->conv == NULL)) || (out->error != 0))
1845
0
        return(0);
1846
1847
0
    if (out->encoder != NULL)
1848
0
        return(xmlBufUse(out->conv));
1849
1850
0
    return(xmlBufUse(out->buffer));
1851
0
}
1852
1853
1854
#endif /* LIBXML_OUTPUT_ENABLED */
1855
1856
/**
1857
 * Create a buffered parser input for the progressive parsing for the input
1858
 * from a file descriptor
1859
 *
1860
 * @deprecated Use #xmlNewInputFromFd.
1861
 *
1862
 * The encoding argument is deprecated and should be set to
1863
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1864
 * #xmlSwitchEncoding or #xmlSwitchEncodingName later on.
1865
 *
1866
 * @param fd  a file descriptor number
1867
 * @param enc  the charset encoding if known (deprecated)
1868
 * @returns the new parser input or NULL
1869
 */
1870
xmlParserInputBuffer *
1871
0
xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1872
0
    xmlParserInputBufferPtr ret;
1873
1874
0
    if (fd < 0) return(NULL);
1875
1876
0
    ret = xmlAllocParserInputBuffer(enc);
1877
0
    if (ret != NULL) {
1878
0
        xmlFdIOCtxt *fdctxt;
1879
1880
0
        fdctxt = xmlMalloc(sizeof(*fdctxt));
1881
0
        if (fdctxt == NULL) {
1882
0
            return(NULL);
1883
0
        }
1884
0
        fdctxt->fd = fd;
1885
1886
0
        ret->context = fdctxt;
1887
0
  ret->readcallback = xmlFdRead;
1888
0
        ret->closecallback = xmlFdFree;
1889
0
    }
1890
1891
0
    return(ret);
1892
0
}
1893
1894
typedef struct {
1895
    const char *cur;
1896
    size_t size;
1897
} xmlMemIOCtxt;
1898
1899
static int
1900
0
xmlMemRead(void *vctxt, char *buf, int size) {
1901
0
    xmlMemIOCtxt *ctxt = vctxt;
1902
1903
0
    if ((size_t) size > ctxt->size)
1904
0
        size = ctxt->size;
1905
1906
0
    memcpy(buf, ctxt->cur, size);
1907
0
    ctxt->cur += size;
1908
0
    ctxt->size -= size;
1909
1910
0
    return size;
1911
0
}
1912
1913
static int
1914
0
xmlMemClose(void *vctxt) {
1915
0
    xmlMemIOCtxt *ctxt = vctxt;
1916
1917
0
    xmlFree(ctxt);
1918
0
    return(0);
1919
0
}
1920
1921
/**
1922
 * Create an input buffer for memory.
1923
 *
1924
 * @param mem  memory buffer
1925
 * @param size  size of buffer
1926
 * @param flags  flags
1927
 * @param enc  the charset encoding if known (deprecated)
1928
 * @returns the new input buffer or NULL.
1929
 */
1930
xmlParserInputBuffer *
1931
xmlNewInputBufferMemory(const void *mem, size_t size,
1932
21.3k
                        xmlParserInputFlags flags, xmlCharEncoding enc) {
1933
21.3k
    xmlParserInputBufferPtr ret;
1934
1935
21.3k
    if ((flags & XML_INPUT_BUF_STATIC) &&
1936
0
        ((flags & XML_INPUT_BUF_ZERO_TERMINATED) == 0)) {
1937
0
        xmlMemIOCtxt *ctxt;
1938
1939
        /*
1940
         * Static buffer without zero terminator.
1941
         * Stream memory to avoid a copy.
1942
         */
1943
0
        ret = xmlAllocParserInputBuffer(enc);
1944
0
        if (ret == NULL)
1945
0
            return(NULL);
1946
1947
0
        ctxt = xmlMalloc(sizeof(*ctxt));
1948
0
        if (ctxt == NULL) {
1949
0
            xmlFreeParserInputBuffer(ret);
1950
0
            return(NULL);
1951
0
        }
1952
1953
0
        ctxt->cur = mem;
1954
0
        ctxt->size = size;
1955
1956
0
        ret->context = ctxt;
1957
0
        ret->readcallback = xmlMemRead;
1958
0
        ret->closecallback = xmlMemClose;
1959
21.3k
    } else {
1960
21.3k
        ret = xmlMalloc(sizeof(*ret));
1961
21.3k
        if (ret == NULL)
1962
0
            return(NULL);
1963
21.3k
        memset(ret, 0, sizeof(xmlParserInputBuffer));
1964
21.3k
        ret->compressed = -1;
1965
1966
21.3k
        ret->buffer = xmlBufCreateMem((const xmlChar *) mem, size,
1967
21.3k
                                      (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1968
21.3k
        if (ret->buffer == NULL) {
1969
0
            xmlFree(ret);
1970
0
            return(NULL);
1971
0
        }
1972
21.3k
    }
1973
1974
21.3k
    return(ret);
1975
21.3k
}
1976
1977
/**
1978
 * Create a parser input buffer for parsing from a memory area.
1979
 *
1980
 * @deprecated Use #xmlNewInputFromMemory.
1981
 *
1982
 * This function makes a copy of the whole input buffer. If you are sure
1983
 * that the contents of the buffer will remain valid until the document
1984
 * was parsed, you can avoid the copy by using
1985
 * #xmlParserInputBufferCreateStatic.
1986
 *
1987
 * The encoding argument is deprecated and should be set to
1988
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1989
 * #xmlSwitchEncoding or #xmlSwitchEncodingName later on.
1990
 *
1991
 * @param mem  the memory input
1992
 * @param size  the length of the memory block
1993
 * @param enc  the charset encoding if known (deprecated)
1994
 * @returns the new parser input or NULL in case of error.
1995
 */
1996
xmlParserInputBuffer *
1997
0
xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
1998
0
    if ((mem == NULL) || (size < 0))
1999
0
        return(NULL);
2000
2001
0
    return(xmlNewInputBufferMemory(mem, size, 0, enc));
2002
0
}
2003
2004
/**
2005
 * Create a parser input buffer for parsing from a memory area.
2006
 *
2007
 * @deprecated Use #xmlNewInputFromMemory.
2008
 *
2009
 * This functions assumes that the contents of the input buffer remain
2010
 * valid until the document was parsed. Use #xmlParserInputBufferCreateMem
2011
 * otherwise.
2012
 *
2013
 * The encoding argument is deprecated and should be set to
2014
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
2015
 * #xmlSwitchEncoding or #xmlSwitchEncodingName later on.
2016
 *
2017
 * @param mem  the memory input
2018
 * @param size  the length of the memory block
2019
 * @param enc  the charset encoding if known
2020
 * @returns the new parser input or NULL in case of error.
2021
 */
2022
xmlParserInputBuffer *
2023
xmlParserInputBufferCreateStatic(const char *mem, int size,
2024
0
                                 xmlCharEncoding enc) {
2025
0
    if ((mem == NULL) || (size < 0))
2026
0
        return(NULL);
2027
2028
0
    return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
2029
0
}
2030
2031
/**
2032
 * Create an input buffer for a null-terminated C string.
2033
 *
2034
 * @deprecated Use #xmlNewInputFromString.
2035
 *
2036
 * @param str  C string
2037
 * @param flags  flags
2038
 * @returns the new input buffer or NULL.
2039
 */
2040
xmlParserInputBuffer *
2041
39.9k
xmlNewInputBufferString(const char *str, xmlParserInputFlags flags) {
2042
39.9k
    xmlParserInputBufferPtr ret;
2043
2044
39.9k
    ret = xmlMalloc(sizeof(*ret));
2045
39.9k
    if (ret == NULL)
2046
0
  return(NULL);
2047
39.9k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
2048
39.9k
    ret->compressed = -1;
2049
2050
39.9k
    ret->buffer = xmlBufCreateMem((const xmlChar *) str, strlen(str),
2051
39.9k
                                  (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
2052
39.9k
    if (ret->buffer == NULL) {
2053
0
        xmlFree(ret);
2054
0
  return(NULL);
2055
0
    }
2056
2057
39.9k
    return(ret);
2058
39.9k
}
2059
2060
#ifdef LIBXML_OUTPUT_ENABLED
2061
/**
2062
 * Create a buffered output for the progressive saving
2063
 * to a file descriptor
2064
 *
2065
 * Consumes `encoder` but not in error case.
2066
 *
2067
 * @param fd  a file descriptor number
2068
 * @param encoder  the encoding converter or NULL
2069
 * @returns the new parser output or NULL
2070
 */
2071
xmlOutputBuffer *
2072
0
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandler *encoder) {
2073
0
    xmlOutputBufferPtr ret;
2074
2075
0
    if (fd < 0) {
2076
0
        return(NULL);
2077
0
    }
2078
2079
0
    ret = xmlAllocOutputBuffer(encoder);
2080
0
    if (ret != NULL) {
2081
0
        xmlFdIOCtxt *fdctxt;
2082
2083
0
        fdctxt = xmlMalloc(sizeof(*fdctxt));
2084
0
        if (fdctxt == NULL) {
2085
0
            return(NULL);
2086
0
        }
2087
0
        fdctxt->fd = fd;
2088
2089
0
        ret->context = fdctxt;
2090
0
  ret->writecallback = xmlFdWrite;
2091
0
        ret->closecallback = xmlFdFree;
2092
0
    }
2093
2094
0
    return(ret);
2095
0
}
2096
#endif /* LIBXML_OUTPUT_ENABLED */
2097
2098
/**
2099
 * Create a buffered parser input for the progressive parsing for the input
2100
 * from an I/O handler
2101
 *
2102
 * @deprecated Use #xmlNewInputFromIO.
2103
 *
2104
 * The encoding argument is deprecated and should be set to
2105
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
2106
 * #xmlSwitchEncoding or #xmlSwitchEncodingName later on.
2107
 *
2108
 * @param ioread  an I/O read function
2109
 * @param ioclose  an I/O close function
2110
 * @param ioctx  an I/O handler
2111
 * @param enc  the charset encoding if known (deprecated)
2112
 * @returns the new parser input or NULL
2113
 */
2114
xmlParserInputBuffer *
2115
xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
2116
0
   xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
2117
0
    xmlParserInputBufferPtr ret;
2118
2119
0
    if (ioread == NULL) return(NULL);
2120
2121
0
    ret = xmlAllocParserInputBuffer(enc);
2122
0
    if (ret != NULL) {
2123
0
        ret->context = (void *) ioctx;
2124
0
  ret->readcallback = ioread;
2125
0
  ret->closecallback = ioclose;
2126
0
    }
2127
2128
0
    return(ret);
2129
0
}
2130
2131
#ifdef LIBXML_OUTPUT_ENABLED
2132
/**
2133
 * Create a buffered output for the progressive saving
2134
 * to an I/O handler
2135
 *
2136
 * Consumes `encoder` but not in error case.
2137
 *
2138
 * @param iowrite  an I/O write function
2139
 * @param ioclose  an I/O close function
2140
 * @param ioctx  an I/O handler
2141
 * @param encoder  the charset encoding if known
2142
 * @returns the new parser output or NULL
2143
 */
2144
xmlOutputBuffer *
2145
xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
2146
   xmlOutputCloseCallback  ioclose, void *ioctx,
2147
0
   xmlCharEncodingHandler *encoder) {
2148
0
    xmlOutputBufferPtr ret;
2149
2150
0
    if (iowrite == NULL) {
2151
0
        return(NULL);
2152
0
    }
2153
2154
0
    ret = xmlAllocOutputBuffer(encoder);
2155
0
    if (ret != NULL) {
2156
0
        ret->context = (void *) ioctx;
2157
0
  ret->writecallback = iowrite;
2158
0
  ret->closecallback = ioclose;
2159
0
    }
2160
2161
0
    return(ret);
2162
0
}
2163
#endif /* LIBXML_OUTPUT_ENABLED */
2164
2165
/**
2166
 * Registers a callback for URI input file handling
2167
 *
2168
 * @deprecated Use #xmlCtxtSetResourceLoader or similar functions.
2169
 *
2170
 * @param func  function pointer to the new ParserInputBufferCreateFilenameFunc
2171
 * @returns the old value of the registration function
2172
 */
2173
xmlParserInputBufferCreateFilenameFunc
2174
xmlParserInputBufferCreateFilenameDefault(
2175
        xmlParserInputBufferCreateFilenameFunc func)
2176
0
{
2177
0
    xmlParserInputBufferCreateFilenameFunc old;
2178
2179
0
    old = xmlParserInputBufferCreateFilenameValue;
2180
0
    if (old == NULL)
2181
0
        old = __xmlParserInputBufferCreateFilename;
2182
2183
0
    if (func == __xmlParserInputBufferCreateFilename)
2184
0
        func = NULL;
2185
0
    xmlParserInputBufferCreateFilenameValue = func;
2186
0
    return(old);
2187
0
}
2188
2189
/**
2190
 * Registers a callback for URI output file handling
2191
 *
2192
 * @param func  function pointer to the new OutputBufferCreateFilenameFunc
2193
 * @returns the old value of the registration function
2194
 */
2195
xmlOutputBufferCreateFilenameFunc
2196
xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
2197
0
{
2198
0
    xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
2199
0
#ifdef LIBXML_OUTPUT_ENABLED
2200
0
    if (old == NULL) {
2201
0
    old = __xmlOutputBufferCreateFilename;
2202
0
  }
2203
0
#endif
2204
0
    xmlOutputBufferCreateFilenameValue = func;
2205
0
    return(old);
2206
0
}
2207
2208
/**
2209
 * Push the content of the arry in the input buffer
2210
 * This routine handle the I18N transcoding to internal UTF-8
2211
 * This is used when operating the parser in progressive (push) mode.
2212
 *
2213
 * @deprecated Internal function, don't use.
2214
 *
2215
 * @param in  a buffered parser input
2216
 * @param len  the size in bytes of the array.
2217
 * @param buf  an char array
2218
 * @returns the number of chars read and stored in the buffer, or -1
2219
 *         in case of error.
2220
 */
2221
int
2222
xmlParserInputBufferPush(xmlParserInputBuffer *in,
2223
0
                   int len, const char *buf) {
2224
0
    size_t nbchars = 0;
2225
0
    int ret;
2226
2227
0
    if (len < 0) return(0);
2228
0
    if ((in == NULL) || (in->error)) return(-1);
2229
0
    if (in->encoder != NULL) {
2230
        /*
2231
   * Store the data in the incoming raw buffer
2232
   */
2233
0
        if (in->raw == NULL) {
2234
0
      in->raw = xmlBufCreate(50);
2235
0
            if (in->raw == NULL) {
2236
0
                in->error = XML_ERR_NO_MEMORY;
2237
0
                return(-1);
2238
0
            }
2239
0
  }
2240
0
  ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
2241
0
  if (ret != 0) {
2242
0
            in->error = XML_ERR_NO_MEMORY;
2243
0
      return(-1);
2244
0
        }
2245
2246
  /*
2247
   * convert as much as possible to the parser reading buffer.
2248
   */
2249
0
        nbchars = SIZE_MAX;
2250
0
  if (xmlCharEncInput(in, &nbchars, /* flush */ 0) !=
2251
0
            XML_ENC_ERR_SUCCESS)
2252
0
            return(-1);
2253
0
        if (nbchars > INT_MAX)
2254
0
            nbchars = INT_MAX;
2255
0
    } else {
2256
0
  nbchars = len;
2257
0
        ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
2258
0
  if (ret != 0) {
2259
0
            in->error = XML_ERR_NO_MEMORY;
2260
0
      return(-1);
2261
0
        }
2262
0
    }
2263
0
    return(nbchars);
2264
0
}
2265
2266
/*
2267
 * When reading from an Input channel indicated end of file or error
2268
 * don't reread from it again.
2269
 */
2270
static int
2271
endOfInput (void * context ATTRIBUTE_UNUSED,
2272
      char * buffer ATTRIBUTE_UNUSED,
2273
0
      int len ATTRIBUTE_UNUSED) {
2274
0
    return(0);
2275
0
}
2276
2277
/**
2278
 * Grow up the content of the input buffer, the old data are preserved
2279
 * This routine handle the I18N transcoding to internal UTF-8
2280
 * This routine is used when operating the parser in normal (pull) mode
2281
 *
2282
 * @deprecated Internal function, don't use.
2283
 *
2284
 * @param in  a buffered parser input
2285
 * @param len  indicative value of the amount of chars to read
2286
 * @returns the number of chars read and stored in the buffer, or -1
2287
 *         in case of error.
2288
 */
2289
int
2290
205k
xmlParserInputBufferGrow(xmlParserInputBuffer *in, int len) {
2291
205k
    int res = 0;
2292
2293
205k
    if ((in == NULL) || (in->error))
2294
0
        return(-1);
2295
2296
205k
    if (len < MINLEN)
2297
205k
        len = MINLEN;
2298
2299
    /*
2300
     * Call the read method for this I/O type.
2301
     */
2302
205k
    if (in->readcallback != NULL) {
2303
0
        xmlBufPtr buf;
2304
2305
0
        if (in->encoder == NULL) {
2306
0
            buf = in->buffer;
2307
0
        } else {
2308
            /*
2309
             * Some users only set 'encoder' and expect us to create
2310
             * the raw buffer lazily.
2311
             */
2312
0
            if (in->raw == NULL) {
2313
0
                in->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
2314
0
                if (in->raw == NULL) {
2315
0
                    in->error = XML_ERR_NO_MEMORY;
2316
0
                    return(-1);
2317
0
                }
2318
0
            }
2319
0
            buf = in->raw;
2320
0
        }
2321
2322
0
        if (xmlBufGrow(buf, len) < 0) {
2323
0
            in->error = XML_ERR_NO_MEMORY;
2324
0
            return(-1);
2325
0
        }
2326
2327
0
  res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
2328
0
  if (res <= 0)
2329
0
      in->readcallback = endOfInput;
2330
0
        if (res < 0) {
2331
0
            if (res == -1)
2332
0
                in->error = XML_IO_UNKNOWN;
2333
0
            else
2334
0
                in->error = -res;
2335
0
            return(-1);
2336
0
        }
2337
2338
0
        if (xmlBufAddLen(buf, res) < 0) {
2339
0
            in->error = XML_ERR_NO_MEMORY;
2340
0
            return(-1);
2341
0
        }
2342
0
    }
2343
2344
    /*
2345
     * Handle encoding.
2346
     */
2347
205k
    if (in->encoder != NULL) {
2348
205k
        size_t sizeOut;
2349
2350
        /*
2351
         * Don't convert whole buffer when reading from memory.
2352
         */
2353
205k
        if (in->readcallback == NULL)
2354
205k
            sizeOut = len;
2355
0
        else
2356
0
            sizeOut = SIZE_MAX;
2357
2358
205k
  if (xmlCharEncInput(in, &sizeOut, /* flush */ 0) !=
2359
205k
            XML_ENC_ERR_SUCCESS)
2360
69
      return(-1);
2361
205k
        res = sizeOut;
2362
205k
    }
2363
205k
    return(res);
2364
205k
}
2365
2366
/**
2367
 * Same as #xmlParserInputBufferGrow.
2368
 *
2369
 * @deprecated Internal function, don't use.
2370
 *
2371
 * @param in  a buffered parser input
2372
 * @param len  indicative value of the amount of chars to read
2373
 * @returns the number of chars read and stored in the buffer, or -1
2374
 *         in case of error.
2375
 */
2376
int
2377
0
xmlParserInputBufferRead(xmlParserInputBuffer *in, int len) {
2378
0
    return(xmlParserInputBufferGrow(in, len));
2379
0
}
2380
2381
#ifdef LIBXML_OUTPUT_ENABLED
2382
/**
2383
 * Write the content of the array in the output I/O buffer
2384
 * This routine handle the I18N transcoding from internal UTF-8
2385
 * The buffer is lossless, i.e. will store in case of partial
2386
 * or delayed writes.
2387
 *
2388
 * @param out  a buffered parser output
2389
 * @param len  the size in bytes of the array.
2390
 * @param data  an char array
2391
 * @returns the number of chars immediately written, or -1
2392
 *         in case of error.
2393
 */
2394
int
2395
0
xmlOutputBufferWrite(xmlOutputBuffer *out, int len, const char *data) {
2396
0
    xmlBufPtr buf = NULL;
2397
0
    size_t written = 0;
2398
0
    int ret;
2399
2400
0
    if ((out == NULL) || (out->error))
2401
0
        return(-1);
2402
0
    if (len < 0)
2403
0
        return(0);
2404
2405
0
    ret = xmlBufAdd(out->buffer, (const xmlChar *) data, len);
2406
0
    if (ret != 0) {
2407
0
        out->error = XML_ERR_NO_MEMORY;
2408
0
        return(-1);
2409
0
    }
2410
2411
    /*
2412
     * first handle encoding stuff.
2413
     */
2414
0
    if (out->encoder != NULL) {
2415
        /*
2416
         * Store the data in the incoming raw buffer
2417
         */
2418
0
        if (out->conv == NULL) {
2419
0
            out->conv = xmlBufCreate(MINLEN);
2420
0
            if (out->conv == NULL) {
2421
0
                out->error = XML_ERR_NO_MEMORY;
2422
0
                return(-1);
2423
0
            }
2424
0
        }
2425
2426
        /*
2427
         * convert as much as possible to the parser reading buffer.
2428
         */
2429
0
        if (xmlBufUse(out->buffer) < 256) {
2430
0
            ret = 0;
2431
0
        } else {
2432
0
            ret = xmlCharEncOutput(out, 0);
2433
0
            if (ret < 0)
2434
0
                return(-1);
2435
0
        }
2436
2437
0
        if (out->writecallback)
2438
0
            buf = out->conv;
2439
0
        else
2440
0
            written = ret;
2441
0
    } else {
2442
0
        if (out->writecallback)
2443
0
            buf = out->buffer;
2444
0
        else
2445
0
            written = len;
2446
0
    }
2447
2448
0
    if ((buf != NULL) && (out->writecallback)) {
2449
        /*
2450
         * second write the stuff to the I/O channel
2451
         */
2452
0
        while (1) {
2453
0
            size_t nbchars = xmlBufUse(buf);
2454
2455
0
            if (nbchars < MINLEN)
2456
0
                break;
2457
2458
0
            ret = out->writecallback(out->context,
2459
0
                       (const char *)xmlBufContent(buf), nbchars);
2460
0
            if (ret < 0) {
2461
0
                out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2462
0
                return(-1);
2463
0
            }
2464
0
            if ((ret == 0) || ((size_t) ret > nbchars)) {
2465
0
                out->error = XML_ERR_INTERNAL_ERROR;
2466
0
                return(-1);
2467
0
            }
2468
2469
0
            xmlBufShrink(buf, ret);
2470
0
            written += ret;
2471
0
            if (out->written > INT_MAX - ret)
2472
0
                out->written = INT_MAX;
2473
0
            else
2474
0
                out->written += ret;
2475
0
        }
2476
0
    }
2477
2478
0
    return(written <= INT_MAX ? written : INT_MAX);
2479
0
}
2480
2481
/**
2482
 * Write the content of the string in the output I/O buffer
2483
 * This routine escapes the characters and then handle the I18N
2484
 * transcoding from internal UTF-8
2485
 * The buffer is lossless, i.e. will store in case of partial
2486
 * or delayed writes.
2487
 *
2488
 * @param out  a buffered parser output
2489
 * @param str  a zero terminated UTF-8 string
2490
 * @param escaping  an optional escaping function (or NULL)
2491
 * @returns the number of chars immediately written, or -1
2492
 *         in case of error.
2493
 */
2494
int
2495
xmlOutputBufferWriteEscape(xmlOutputBuffer *out, const xmlChar *str,
2496
0
                           xmlCharEncodingOutputFunc escaping) {
2497
0
    int ret;
2498
0
    int written = 0;
2499
0
    size_t len;
2500
2501
0
    if ((out == NULL) || (out->error) || (str == NULL))
2502
0
        return(-1);
2503
2504
0
    len = strlen((const char *) str);
2505
0
    if (len >= INT_MAX) {
2506
0
        out->error = XML_ERR_RESOURCE_LIMIT;
2507
0
        return(-1);
2508
0
    }
2509
2510
0
    if (escaping == NULL) {
2511
0
        char *escaped = (char *) xmlEscapeText(str, 0);
2512
2513
0
        if (escaped == NULL) {
2514
0
            out->error = XML_ERR_NO_MEMORY;
2515
0
            return(-1);
2516
0
        }
2517
2518
0
        len = strlen(escaped);
2519
0
        if (len >= INT_MAX) {
2520
0
            out->error = XML_ERR_RESOURCE_LIMIT;
2521
0
            return(-1);
2522
0
        }
2523
2524
0
        ret = xmlOutputBufferWrite(out, len, escaped);
2525
2526
0
        xmlFree(escaped);
2527
0
        return(ret);
2528
0
    }
2529
2530
0
    while (len > 0) {
2531
0
        xmlChar buf[1024];
2532
0
        int c_out;
2533
0
        int c_in;
2534
2535
0
  c_out = 1024;
2536
0
  c_in = len;
2537
2538
0
        ret = escaping(buf, &c_out, str, &c_in);
2539
0
        if (ret < 0) {
2540
0
            out->error = XML_ERR_NO_MEMORY;
2541
0
            return(-1);
2542
0
        }
2543
0
        str += c_in;
2544
0
        len -= c_in;
2545
2546
0
        ret = xmlOutputBufferWrite(out, c_out, (char *) buf);
2547
0
        if (ret < 0)
2548
0
            return(ret);
2549
0
        written += ret;
2550
0
    }
2551
2552
0
    return(written);
2553
0
}
2554
2555
/**
2556
 * Write the content of the string in the output I/O buffer
2557
 * This routine handle the I18N transcoding from internal UTF-8
2558
 * The buffer is lossless, i.e. will store in case of partial
2559
 * or delayed writes.
2560
 *
2561
 * @param out  a buffered parser output
2562
 * @param str  a zero terminated C string
2563
 * @returns the number of chars immediately written, or -1
2564
 *         in case of error.
2565
 */
2566
int
2567
0
xmlOutputBufferWriteString(xmlOutputBuffer *out, const char *str) {
2568
0
    int len;
2569
2570
0
    if ((out == NULL) || (out->error)) return(-1);
2571
0
    if (str == NULL)
2572
0
        return(-1);
2573
0
    len = strlen(str);
2574
2575
0
    if (len > 0)
2576
0
  return(xmlOutputBufferWrite(out, len, str));
2577
0
    return(len);
2578
0
}
2579
2580
/**
2581
 * Write a string surrounded by quotes to an output buffer.
2582
 *
2583
 * Uses double quotes if the string contains no double quotes.
2584
 * Otherwise, uses single quotes if the string contains no
2585
 * single quotes. Otherwise, uses double quotes and escapes
2586
 * double quotes.
2587
 *
2588
 * This should only be used to escape system IDs. Currently,
2589
 * we also use it for public IDs and original entity values.
2590
 *
2591
 * @param buf  output buffer
2592
 * @param string  the string to add
2593
 */
2594
void
2595
xmlOutputBufferWriteQuotedString(xmlOutputBuffer *buf,
2596
0
                                 const xmlChar *string) {
2597
0
    const xmlChar *cur, *base;
2598
2599
0
    if ((buf == NULL) || (buf->error))
2600
0
        return;
2601
2602
0
    if (xmlStrchr(string, '\"')) {
2603
0
        if (xmlStrchr(string, '\'')) {
2604
0
      xmlOutputBufferWrite(buf, 1, "\"");
2605
0
            base = cur = string;
2606
0
            while(*cur != 0){
2607
0
                if(*cur == '"'){
2608
0
                    if (base != cur)
2609
0
                        xmlOutputBufferWrite(buf, cur - base,
2610
0
                                             (const char *) base);
2611
0
                    xmlOutputBufferWrite(buf, 6, "&quot;");
2612
0
                    cur++;
2613
0
                    base = cur;
2614
0
                }
2615
0
                else {
2616
0
                    cur++;
2617
0
                }
2618
0
            }
2619
0
            if (base != cur)
2620
0
                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
2621
0
      xmlOutputBufferWrite(buf, 1, "\"");
2622
0
  }
2623
0
        else{
2624
0
      xmlOutputBufferWrite(buf, 1, "'");
2625
0
            xmlOutputBufferWriteString(buf, (const char *) string);
2626
0
      xmlOutputBufferWrite(buf, 1, "'");
2627
0
        }
2628
0
    } else {
2629
0
        xmlOutputBufferWrite(buf, 1, "\"");
2630
0
        xmlOutputBufferWriteString(buf, (const char *) string);
2631
0
        xmlOutputBufferWrite(buf, 1, "\"");
2632
0
    }
2633
0
}
2634
2635
/**
2636
 * flushes the output I/O channel
2637
 *
2638
 * @param out  a buffered output
2639
 * @returns the number of byte written or -1 in case of error.
2640
 */
2641
int
2642
0
xmlOutputBufferFlush(xmlOutputBuffer *out) {
2643
0
    int nbchars = 0, ret = 0;
2644
2645
0
    if ((out == NULL) || (out->error)) return(-1);
2646
    /*
2647
     * first handle encoding stuff.
2648
     */
2649
0
    if ((out->conv != NULL) && (out->encoder != NULL)) {
2650
  /*
2651
   * convert as much as possible to the parser output buffer.
2652
   */
2653
0
  do {
2654
0
      nbchars = xmlCharEncOutput(out, 0);
2655
0
      if (nbchars < 0)
2656
0
    return(-1);
2657
0
  } while (nbchars);
2658
0
    }
2659
2660
    /*
2661
     * second flush the stuff to the I/O channel
2662
     */
2663
0
    if ((out->conv != NULL) && (out->encoder != NULL) &&
2664
0
  (out->writecallback != NULL)) {
2665
0
  ret = out->writecallback(out->context,
2666
0
                                 (const char *)xmlBufContent(out->conv),
2667
0
                                 xmlBufUse(out->conv));
2668
0
  if (ret >= 0)
2669
0
      xmlBufShrink(out->conv, ret);
2670
0
    } else if (out->writecallback != NULL) {
2671
0
  ret = out->writecallback(out->context,
2672
0
                                 (const char *)xmlBufContent(out->buffer),
2673
0
                                 xmlBufUse(out->buffer));
2674
0
  if (ret >= 0)
2675
0
      xmlBufShrink(out->buffer, ret);
2676
0
    }
2677
0
    if (ret < 0) {
2678
0
        out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2679
0
  return(ret);
2680
0
    }
2681
0
    if (out->written > INT_MAX - ret)
2682
0
        out->written = INT_MAX;
2683
0
    else
2684
0
        out->written += ret;
2685
2686
0
    return(ret);
2687
0
}
2688
#endif /* LIBXML_OUTPUT_ENABLED */
2689
2690
/**
2691
 * lookup the directory for that file
2692
 *
2693
 * @param filename  the path to a file
2694
 * @returns a new allocated string containing the directory, or NULL.
2695
 */
2696
char *
2697
0
xmlParserGetDirectory(const char *filename) {
2698
0
    char *ret = NULL;
2699
0
    char dir[1024];
2700
0
    char *cur;
2701
2702
0
    if (filename == NULL) return(NULL);
2703
2704
#if defined(_WIN32)
2705
#   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
2706
#else
2707
0
#   define IS_XMLPGD_SEP(ch) (ch=='/')
2708
0
#endif
2709
2710
0
    strncpy(dir, filename, 1023);
2711
0
    dir[1023] = 0;
2712
0
    cur = &dir[strlen(dir)];
2713
0
    while (cur > dir) {
2714
0
         if (IS_XMLPGD_SEP(*cur)) break;
2715
0
   cur --;
2716
0
    }
2717
0
    if (IS_XMLPGD_SEP(*cur)) {
2718
0
        if (cur == dir) dir[1] = 0;
2719
0
  else *cur = 0;
2720
0
  ret = xmlMemStrdup(dir);
2721
0
    } else {
2722
0
        ret = xmlMemStrdup(".");
2723
0
    }
2724
0
    return(ret);
2725
0
#undef IS_XMLPGD_SEP
2726
0
}
2727
2728
/**
2729
 * Like #xmlCheckFilename but handles file URIs.
2730
 *
2731
 * @deprecated Internal function, don't use.
2732
 *
2733
 * @param filename  the path to check
2734
 * @returns 0, 1, or 2.
2735
 */
2736
int
2737
0
xmlNoNetExists(const char *filename) {
2738
0
    char *fromUri;
2739
0
    int ret;
2740
2741
0
    if (filename == NULL)
2742
0
  return(0);
2743
2744
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
2745
0
        return(0);
2746
2747
0
    if (fromUri != NULL)
2748
0
        filename = fromUri;
2749
2750
0
    ret =  xmlCheckFilename(filename);
2751
2752
0
    xmlFree(fromUri);
2753
0
    return(ret);
2754
0
}
2755
2756
/************************************************************************
2757
 *                  *
2758
 *      Input/output callbacks        *
2759
 *                  *
2760
 ************************************************************************/
2761
2762
/**
2763
 * Initialize callback tables.
2764
 */
2765
void
2766
xmlInitIOCallbacks(void)
2767
1
{
2768
1
    xmlInputCallbackNr = 1;
2769
1
    xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2770
2771
1
#ifdef LIBXML_OUTPUT_ENABLED
2772
1
    xmlOutputCallbackNr = 1;
2773
1
    xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2774
1
#endif
2775
1
}
2776
2777
/**
2778
 * Register a new set of I/O callback for handling parser input.
2779
 *
2780
 * @deprecated Use #xmlCtxtSetResourceLoader or similar functions.
2781
 *
2782
 * @param matchFunc  the xmlInputMatchCallback
2783
 * @param openFunc  the xmlInputOpenCallback
2784
 * @param readFunc  the xmlInputReadCallback
2785
 * @param closeFunc  the xmlInputCloseCallback
2786
 * @returns the registered handler number or -1 in case of error
2787
 */
2788
int
2789
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2790
  xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2791
0
  xmlInputCloseCallback closeFunc) {
2792
0
    xmlInitParser();
2793
2794
0
    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2795
0
  return(-1);
2796
0
    }
2797
0
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2798
0
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2799
0
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2800
0
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2801
0
    return(xmlInputCallbackNr++);
2802
0
}
2803
2804
/**
2805
 * Registers the default compiled-in I/O handlers.
2806
 */
2807
void
2808
0
xmlRegisterDefaultInputCallbacks(void) {
2809
0
    xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2810
0
}
2811
2812
/**
2813
 * Clear the top input callback from the input stack. this includes the
2814
 * compiled-in I/O.
2815
 *
2816
 * @returns the number of input callback registered or -1 in case of error.
2817
 */
2818
int
2819
xmlPopInputCallbacks(void)
2820
0
{
2821
0
    xmlInitParser();
2822
2823
0
    if (xmlInputCallbackNr <= 0)
2824
0
        return(-1);
2825
2826
0
    xmlInputCallbackNr--;
2827
2828
0
    return(xmlInputCallbackNr);
2829
0
}
2830
2831
/**
2832
 * clears the entire input callback table. this includes the
2833
 * compiled-in I/O.
2834
 */
2835
void
2836
xmlCleanupInputCallbacks(void)
2837
0
{
2838
0
    xmlInitParser();
2839
2840
0
    xmlInputCallbackNr = 0;
2841
0
}
2842
2843
#ifdef LIBXML_OUTPUT_ENABLED
2844
/**
2845
 * Register a new set of I/O callback for handling output.
2846
 *
2847
 * @param matchFunc  the xmlOutputMatchCallback
2848
 * @param openFunc  the xmlOutputOpenCallback
2849
 * @param writeFunc  the xmlOutputWriteCallback
2850
 * @param closeFunc  the xmlOutputCloseCallback
2851
 * @returns the registered handler number or -1 in case of error
2852
 */
2853
int
2854
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2855
  xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2856
0
  xmlOutputCloseCallback closeFunc) {
2857
0
    xmlInitParser();
2858
2859
0
    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2860
0
  return(-1);
2861
0
    }
2862
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2863
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2864
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2865
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2866
0
    return(xmlOutputCallbackNr++);
2867
0
}
2868
2869
/**
2870
 * Registers the default compiled-in I/O handlers.
2871
 */
2872
void
2873
0
xmlRegisterDefaultOutputCallbacks (void) {
2874
0
    xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2875
0
}
2876
2877
/**
2878
 * Remove the top output callbacks from the output stack. This includes the
2879
 * compiled-in I/O.
2880
 *
2881
 * @returns the number of output callback registered or -1 in case of error.
2882
 */
2883
int
2884
xmlPopOutputCallbacks(void)
2885
0
{
2886
0
    xmlInitParser();
2887
2888
0
    if (xmlOutputCallbackNr <= 0)
2889
0
        return(-1);
2890
2891
0
    xmlOutputCallbackNr--;
2892
2893
0
    return(xmlOutputCallbackNr);
2894
0
}
2895
2896
/**
2897
 * clears the entire output callback table. this includes the
2898
 * compiled-in I/O callbacks.
2899
 */
2900
void
2901
xmlCleanupOutputCallbacks(void)
2902
0
{
2903
0
    xmlInitParser();
2904
2905
0
    xmlOutputCallbackNr = 0;
2906
0
}
2907
#endif /* LIBXML_OUTPUT_ENABLED */
2908