Coverage Report

Created: 2026-01-19 06:49

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