Coverage Report

Created: 2026-05-28 07:01

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
110M
#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
209M
xmlSerializeHexCharRef(char *buf, int val) {
124
209M
    char *out = buf;
125
209M
    int shift = 0, bits;
126
127
209M
    *out++ = '&';
128
209M
    *out++ = '#';
129
209M
    *out++ = 'x';
130
131
209M
    bits = val;
132
209M
    if (bits & 0xFF0000) {
133
75.8k
        shift = 16;
134
75.8k
        bits &= 0xFF0000;
135
209M
    } else if (bits & 0x00FF00) {
136
209M
        shift = 8;
137
209M
        bits &= 0x00FF00;
138
209M
    }
139
209M
    if (bits & 0xF0F0F0) {
140
209M
        shift += 4;
141
209M
    }
142
143
836M
    do {
144
836M
        int d = (val >> shift) & 0x0F;
145
146
836M
        if (d < 10)
147
453k
            *out++ = '0' + d;
148
836M
        else
149
836M
            *out++ = 'A' + (d - 10);
150
151
836M
  shift -= 4;
152
836M
    } while (shift >= 0);
153
154
209M
    *out++ = ';';
155
156
209M
    return(out - buf);
157
209M
}
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
13.0k
        if (flags & XML_ESCAPE_ATTR)
185
11.6k
            tab = htmlEscapeTabAttr;
186
1.37k
        else
187
1.37k
            tab = htmlEscapeTab;
188
13.0k
    }
189
92.6k
    else
190
92.6k
#endif
191
92.6k
    {
192
92.6k
        if (flags & XML_ESCAPE_QUOT)
193
1.84k
            tab = xmlEscapeTabQuot;
194
90.8k
        else if (flags & XML_ESCAPE_ATTR)
195
89.2k
            tab = xmlEscapeTabAttr;
196
1.62k
        else
197
1.62k
            tab = xmlEscapeTab;
198
92.6k
    }
199
200
105k
    buffer = xmlMalloc(size + 1);
201
105k
    if (buffer == NULL)
202
19
        return(NULL);
203
105k
    out = buffer;
204
205
105k
    cur = string;
206
207
54.7M
    while (*cur != 0) {
208
54.7M
        char tempBuf[12];
209
54.7M
        const xmlChar *base;
210
54.7M
        const char *repl;
211
54.7M
        size_t used;
212
54.7M
        size_t replSize;
213
54.7M
        size_t unescapedSize;
214
54.7M
        size_t totalSize;
215
54.7M
        int c;
216
54.7M
        int offset;
217
218
54.7M
        base = cur;
219
54.7M
        offset = -1;
220
221
115M
        while (1) {
222
115M
            c = *cur;
223
224
115M
            if (c < 0x80) {
225
68.9M
                offset = tab[c];
226
68.9M
                if (offset >= 0)
227
11.7M
                    break;
228
68.9M
            } else if (flags & XML_ESCAPE_NON_ASCII) {
229
43.0M
                break;
230
43.0M
            }
231
232
60.5M
            cur += 1;
233
60.5M
        }
234
235
54.7M
        unescapedSize = cur - base;
236
237
54.7M
        if (offset >= 0) {
238
11.7M
            if (c == 0) {
239
87.9k
                replSize = 0;
240
87.9k
                repl = "";
241
11.6M
            } else {
242
11.6M
                replSize = xmlEscapeContent[offset],
243
11.6M
                repl = &xmlEscapeContent[offset+1];
244
11.6M
                cur += 1;
245
11.6M
            }
246
43.0M
        } else {
247
43.0M
            int val = 0, len = 4;
248
249
43.0M
            val = xmlGetUTF8Char(cur, &len);
250
43.0M
            if (val < 0) {
251
9.82M
                val = 0xFFFD;
252
9.82M
                cur += 1;
253
33.1M
            } else {
254
33.1M
                if ((val == 0xFFFE) || (val == 0xFFFF))
255
925
                    val = 0xFFFD;
256
33.1M
                cur += len;
257
33.1M
            }
258
259
43.0M
            replSize = xmlSerializeHexCharRef(tempBuf, val);
260
43.0M
            repl = tempBuf;
261
43.0M
        }
262
263
54.7M
        used = out - buffer;
264
54.7M
        totalSize = unescapedSize + replSize;
265
266
54.7M
        if (totalSize > size - used) {
267
37.6k
            xmlChar *tmp;
268
37.6k
            size_t newSize;
269
270
37.6k
            if ((size > (SIZE_MAX - 1) / 2) ||
271
37.6k
                (totalSize > (SIZE_MAX - 1) / 2 - size)) {
272
0
                xmlFree(buffer);
273
0
                return(NULL);
274
0
            }
275
37.6k
            newSize = size + totalSize;
276
37.6k
            if (*cur != 0)
277
36.7k
                newSize *= 2;
278
37.6k
            tmp = xmlRealloc(buffer, newSize + 1);
279
37.6k
            if (tmp == NULL) {
280
8
                xmlFree(buffer);
281
8
                return(NULL);
282
8
            }
283
37.6k
            buffer = tmp;
284
37.6k
            size = newSize;
285
37.6k
            out = buffer + used;
286
37.6k
        }
287
288
54.7M
        memcpy(out, base, unescapedSize);
289
54.7M
        out += unescapedSize;
290
54.7M
        memcpy(out, repl, replSize);
291
54.7M
        out += replSize;
292
293
54.7M
        if (c == 0)
294
87.9k
            break;
295
296
54.6M
        base = cur;
297
54.6M
    }
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
3.00M
                 unsigned flags) {
307
3.00M
    const xmlChar *cur;
308
3.00M
    const signed char *tab;
309
310
3.00M
    if (string == NULL)
311
353
        return;
312
313
3.00M
#ifdef LIBXML_HTML_ENABLED
314
3.00M
    if (flags & XML_ESCAPE_HTML) {
315
171k
        if (flags & XML_ESCAPE_ATTR)
316
48.3k
            tab = htmlEscapeTabAttr;
317
122k
        else
318
122k
            tab = htmlEscapeTab;
319
171k
    }
320
2.83M
    else
321
2.83M
#endif
322
2.83M
    {
323
2.83M
        if (flags & XML_ESCAPE_QUOT)
324
0
            tab = xmlEscapeTabQuot;
325
2.83M
        else if (flags & XML_ESCAPE_ATTR)
326
2.03M
            tab = xmlEscapeTabAttr;
327
796k
        else
328
796k
            tab = xmlEscapeTab;
329
2.83M
    }
330
331
3.00M
    cur = string;
332
333
249M
    while (1) {
334
249M
        const xmlChar *base;
335
249M
        int c;
336
249M
        int offset;
337
338
249M
        base = cur;
339
249M
        offset = -1;
340
341
1.55G
        while (1) {
342
1.55G
            if ((size_t) (cur - string) >= maxSize)
343
0
                break;
344
345
1.55G
            c = (unsigned char) *cur;
346
347
1.55G
            if (c < 0x80) {
348
519M
                offset = tab[c];
349
519M
                if (offset >= 0)
350
82.9M
                    break;
351
1.03G
            } else if (flags & XML_ESCAPE_NON_ASCII) {
352
166M
                break;
353
166M
            }
354
355
1.30G
            cur += 1;
356
1.30G
        }
357
358
249M
        if (cur > base)
359
48.9M
            xmlOutputBufferWrite(buf, cur - base, (char *) base);
360
361
249M
        if ((size_t) (cur - string) >= maxSize)
362
0
            break;
363
364
249M
        if (offset >= 0) {
365
82.9M
            if (c == 0)
366
3.00M
                break;
367
368
79.9M
            xmlOutputBufferWrite(buf, xmlEscapeContent[offset],
369
79.9M
                                 &xmlEscapeContent[offset+1]);
370
79.9M
            cur += 1;
371
166M
        } else {
372
166M
            char tempBuf[12];
373
166M
            int tempSize;
374
166M
            int val = 0, len = 4;
375
376
166M
            val = xmlGetUTF8Char(cur, &len);
377
166M
            if (val < 0) {
378
119M
                val = 0xFFFD;
379
119M
                cur += 1;
380
119M
            } else {
381
47.0M
                if ((val == 0xFFFE) || (val == 0xFFFF))
382
1.11k
                    val = 0xFFFD;
383
47.0M
                cur += len;
384
47.0M
            }
385
386
166M
            tempSize = xmlSerializeHexCharRef(tempBuf, val);
387
166M
            xmlOutputBufferWrite(buf, tempSize, tempBuf);
388
166M
        }
389
249M
    }
390
3.00M
}
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
2.41k
{
408
2.41k
    xmlParserErrors code;
409
410
2.41k
    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
2.17k
        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
81
        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
162
        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
2.41k
    }
561
562
2.41k
    return(code);
563
2.41k
}
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
23.2k
xmlConvertUriToPath(const char *uri, char **out) {
682
23.2k
    const char *escaped;
683
23.2k
    char *unescaped;
684
#ifdef LIBXML_WINPATH_ENABLED
685
    xmlChar ch;
686
#endif
687
688
23.2k
    *out = NULL;
689
690
23.2k
    if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file://localhost/", 17)) {
691
0
        escaped = &uri[16];
692
23.2k
    } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:///", 8)) {
693
353
        escaped = &uri[7];
694
22.9k
    } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:/", 6)) {
695
        /* lots of generators seems to lazy to read RFC 1738 */
696
1.40k
        escaped = &uri[5];
697
21.5k
    } else {
698
21.5k
        return(1);
699
21.5k
    }
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
1.76k
    unescaped = xmlURIUnescapeString(escaped, 0, NULL);
712
1.76k
    if (unescaped == NULL)
713
2
        return(-1);
714
715
1.75k
    *out = unescaped;
716
1.75k
    return(0);
717
1.76k
}
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
23.2k
xmlFdOpen(const char *filename, int write, int *out) {
731
23.2k
    char *fromUri = NULL;
732
23.2k
    int flags;
733
23.2k
    int fd;
734
23.2k
    xmlParserErrors ret;
735
736
23.2k
    *out = -1;
737
23.2k
    if (filename == NULL)
738
0
        return(XML_ERR_ARGUMENT);
739
740
23.2k
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
741
2
        return(XML_ERR_NO_MEMORY);
742
743
23.2k
    if (fromUri != NULL)
744
1.75k
        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
23.2k
    if (write)
764
0
        flags = O_WRONLY | O_CREAT | O_TRUNC;
765
23.2k
    else
766
23.2k
        flags = O_RDONLY;
767
23.2k
    fd = open(filename, flags, 0666);
768
23.2k
#endif /* WIN32 */
769
770
23.2k
    if (fd < 0) {
771
        /*
772
         * Windows and possibly other platforms return EINVAL
773
         * for invalid filenames.
774
         */
775
18.7k
        if ((errno == ENOENT) || (errno == EINVAL)) {
776
18.5k
            ret = XML_IO_ENOENT;
777
18.5k
        } else {
778
243
            ret = xmlIOErr(errno);
779
243
        }
780
18.7k
    } else {
781
4.50k
        *out = fd;
782
4.50k
        ret = XML_ERR_OK;
783
4.50k
    }
784
785
23.2k
    xmlFree(fromUri);
786
23.2k
    return(ret);
787
23.2k
}
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
253k
xmlFdRead(void *context, char *buffer, int len) {
799
253k
    xmlFdIOCtxt *fdctxt = context;
800
253k
    int fd = fdctxt->fd;
801
253k
    int ret = 0;
802
253k
    int bytes;
803
804
503k
    while (len > 0) {
805
255k
        bytes = read(fd, buffer, len);
806
255k
        if (bytes < 0) {
807
            /*
808
             * If we already got some bytes, return them without
809
             * raising an error.
810
             */
811
2.17k
            if (ret > 0)
812
0
                break;
813
2.17k
            return(-xmlIOErr(errno));
814
2.17k
        }
815
253k
        if (bytes == 0)
816
3.28k
            break;
817
250k
        ret += bytes;
818
250k
        buffer += bytes;
819
250k
        len -= bytes;
820
250k
    }
821
822
251k
    return(ret);
823
253k
}
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
2
xmlFdWrite(void *context, const char *buffer, int len) {
836
2
    xmlFdIOCtxt *fdctxt = context;
837
2
    int fd = fdctxt->fd;
838
2
    int ret = 0;
839
2
    int bytes;
840
841
3
    while (len > 0) {
842
1
  bytes = write(fd, buffer, len);
843
1
  if (bytes < 0)
844
0
            return(-xmlIOErr(errno));
845
1
        ret += bytes;
846
1
        buffer += bytes;
847
1
        len -= bytes;
848
1
    }
849
850
2
    return(ret);
851
2
}
852
#endif /* LIBXML_OUTPUT_ENABLED */
853
854
static int
855
1
xmlFdFree(void *context) {
856
1
    xmlFree(context);
857
1
    return(XML_ERR_OK);
858
1
}
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
4.50k
xmlFdClose (void * context) {
868
4.50k
    xmlFdIOCtxt *fdctxt = context;
869
4.50k
    int fd = fdctxt->fd;
870
4.50k
    int ret;
871
872
4.50k
    ret = close(fd);
873
874
4.50k
    xmlFree(fdctxt);
875
876
4.50k
    if (ret < 0)
877
0
        return(xmlIOErr(errno));
878
879
4.50k
    return(XML_ERR_OK);
880
4.50k
}
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
143k
xmlBufferWrite (void * context, const char * buffer, int len) {
1078
143k
    int ret;
1079
1080
143k
    ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
1081
143k
    if (ret != 0)
1082
17
        return(-XML_ERR_NO_MEMORY);
1083
143k
    return(len);
1084
143k
}
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
446
xmlGzfileClose (void * context) {
1139
446
    if (gzclose((gzFile) context) != Z_OK)
1140
0
        return(XML_IO_UNKNOWN);
1141
446
    return(0);
1142
446
}
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
892
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
892
    return lseek(fd, offset, whence);
1177
892
#endif
1178
892
}
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
4.50k
               xmlParserInputFlags flags) {
1194
4.50k
    xmlFdIOCtxt *fdctxt;
1195
4.50k
    int copy;
1196
1197
4.50k
    (void) flags;
1198
1199
4.50k
#ifdef LIBXML_ZLIB_ENABLED
1200
4.50k
    if (flags & XML_INPUT_UNZIP) {
1201
446
        gzFile gzStream;
1202
446
        xmlFileOffset pos;
1203
1204
446
        pos = xmlSeek(fd, 0, SEEK_CUR);
1205
1206
446
        copy = dup(fd);
1207
446
        if (copy == -1)
1208
0
            return(xmlIOErr(errno));
1209
1210
446
        gzStream = gzdopen(copy, "rb");
1211
1212
446
        if (gzStream == NULL) {
1213
0
            close(copy);
1214
446
        } else {
1215
446
            int compressed = (gzdirect(gzStream) == 0);
1216
1217
446
            if ((compressed) ||
1218
                /* Try to rewind if not gzip compressed */
1219
446
                (pos < 0) ||
1220
446
                (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
446
            xmlGzfileClose(gzStream);
1234
446
        }
1235
446
    }
1236
4.50k
#endif /* LIBXML_ZLIB_ENABLED */
1237
1238
4.50k
    copy = dup(fd);
1239
4.50k
    if (copy == -1)
1240
0
        return(xmlIOErr(errno));
1241
1242
4.50k
    fdctxt = xmlMalloc(sizeof(*fdctxt));
1243
4.50k
    if (fdctxt == NULL) {
1244
4
        close(copy);
1245
4
        return(XML_ERR_NO_MEMORY);
1246
4
    }
1247
4.50k
    fdctxt->fd = copy;
1248
1249
4.50k
    buf->context = fdctxt;
1250
4.50k
    buf->readcallback = xmlFdRead;
1251
4.50k
    buf->closecallback = xmlFdClose;
1252
1253
4.50k
    return(XML_ERR_OK);
1254
4.50k
}
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
269k
xmlAllocParserInputBuffer(xmlCharEncoding enc) {
1333
269k
    xmlParserInputBufferPtr ret;
1334
1335
269k
    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1336
269k
    if (ret == NULL) {
1337
27
  return(NULL);
1338
27
    }
1339
269k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
1340
269k
    ret->buffer = xmlBufCreate(XML_IO_BUFFER_SIZE);
1341
269k
    if (ret->buffer == NULL) {
1342
49
        xmlFree(ret);
1343
49
  return(NULL);
1344
49
    }
1345
269k
    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
269k
    if (ret->encoder != NULL)
1353
0
        ret->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
1354
269k
    else
1355
269k
        ret->raw = NULL;
1356
269k
    ret->readcallback = NULL;
1357
269k
    ret->closecallback = NULL;
1358
269k
    ret->context = NULL;
1359
269k
    ret->compressed = -1;
1360
269k
    ret->rawconsumed = 0;
1361
1362
269k
    return(ret);
1363
269k
}
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
131k
xmlAllocOutputBuffer(xmlCharEncodingHandler *encoder) {
1376
131k
    xmlOutputBufferPtr ret;
1377
1378
131k
    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
1379
131k
    if (ret == NULL) {
1380
192
  return(NULL);
1381
192
    }
1382
131k
    memset(ret, 0, sizeof(xmlOutputBuffer));
1383
131k
    ret->buffer = xmlBufCreate(MINLEN);
1384
131k
    if (ret->buffer == NULL) {
1385
326
        xmlFree(ret);
1386
326
  return(NULL);
1387
326
    }
1388
1389
131k
    ret->encoder = encoder;
1390
131k
    if (encoder != NULL) {
1391
5.79k
        ret->conv = xmlBufCreate(MINLEN);
1392
5.79k
  if (ret->conv == NULL) {
1393
2
            xmlBufFree(ret->buffer);
1394
2
            xmlFree(ret);
1395
2
      return(NULL);
1396
2
  }
1397
1398
  /*
1399
   * This call is designed to initiate the encoder state
1400
   */
1401
5.79k
  xmlCharEncOutput(ret, 1);
1402
5.79k
    } else
1403
125k
        ret->conv = NULL;
1404
131k
    ret->writecallback = NULL;
1405
131k
    ret->closecallback = NULL;
1406
131k
    ret->context = NULL;
1407
131k
    ret->written = 0;
1408
1409
131k
    return(ret);
1410
131k
}
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
1.32M
xmlFreeParserInputBuffer(xmlParserInputBuffer *in) {
1420
1.32M
    if (in == NULL) return;
1421
1422
1.32M
    if (in->raw) {
1423
136k
        xmlBufFree(in->raw);
1424
136k
  in->raw = NULL;
1425
136k
    }
1426
1.32M
    if (in->encoder != NULL) {
1427
136k
        xmlCharEncCloseFunc(in->encoder);
1428
136k
    }
1429
1.32M
    if (in->closecallback != NULL) {
1430
150k
  in->closecallback(in->context);
1431
150k
    }
1432
1.32M
    if (in->buffer != NULL) {
1433
1.32M
        xmlBufFree(in->buffer);
1434
1.32M
  in->buffer = NULL;
1435
1.32M
    }
1436
1437
1.32M
    xmlFree(in);
1438
1.32M
}
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
133k
{
1452
133k
    int ret;
1453
1454
133k
    if (out == NULL)
1455
2.26k
        return (-1);
1456
1457
131k
    if (out->writecallback != NULL)
1458
56.6k
        xmlOutputBufferFlush(out);
1459
1460
131k
    if (out->closecallback != NULL) {
1461
34.0k
        int code = out->closecallback(out->context);
1462
1463
34.0k
        if ((code != XML_ERR_OK) &&
1464
29
            (!xmlIsCatastrophicError(XML_ERR_FATAL, out->error))) {
1465
29
            if (code < 0)
1466
0
                out->error = XML_IO_UNKNOWN;
1467
29
            else
1468
29
                out->error = code;
1469
29
        }
1470
34.0k
    }
1471
1472
131k
    if (out->error != XML_ERR_OK)
1473
4.14k
        ret = -out->error;
1474
127k
    else
1475
127k
        ret = out->written;
1476
1477
131k
    if (out->conv) {
1478
5.79k
        xmlBufFree(out->conv);
1479
5.79k
        out->conv = NULL;
1480
5.79k
    }
1481
131k
    if (out->encoder != NULL) {
1482
5.79k
        xmlCharEncCloseFunc(out->encoder);
1483
5.79k
    }
1484
131k
    if (out->buffer != NULL) {
1485
131k
        xmlBufFree(out->buffer);
1486
131k
        out->buffer = NULL;
1487
131k
    }
1488
1489
131k
    xmlFree(out);
1490
1491
131k
    return(ret);
1492
133k
}
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
23.2k
                              xmlParserInputBuffer **out) {
1506
23.2k
    xmlParserInputBufferPtr buf;
1507
23.2k
    xmlParserErrors ret;
1508
23.2k
    int i;
1509
1510
23.2k
    xmlInitParser();
1511
1512
23.2k
    *out = NULL;
1513
23.2k
    if (URI == NULL)
1514
0
        return(XML_ERR_ARGUMENT);
1515
1516
    /*
1517
     * Allocate the Input buffer front-end.
1518
     */
1519
23.2k
    buf = xmlAllocParserInputBuffer(enc);
1520
23.2k
    if (buf == NULL)
1521
25
        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
23.2k
    ret = XML_IO_ENOENT;
1528
41.7k
    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
1529
23.2k
        xmlInputCallback *cb = &xmlInputCallbackTable[i];
1530
1531
23.2k
        if (cb->matchcallback == xmlIODefaultMatch) {
1532
23.2k
            int fd;
1533
1534
23.2k
            ret = xmlFdOpen(URI, 0, &fd);
1535
1536
23.2k
            if (ret == XML_ERR_OK) {
1537
4.50k
                ret = xmlInputFromFd(buf, fd, flags);
1538
4.50k
                close(fd);
1539
4.50k
                break;
1540
18.7k
            } else if (ret != XML_IO_ENOENT) {
1541
245
                break;
1542
245
            }
1543
23.2k
        } 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
23.2k
    }
1554
23.2k
    if (ret != XML_ERR_OK) {
1555
18.7k
        xmlFreeParserInputBuffer(buf);
1556
18.7k
        *out = NULL;
1557
18.7k
  return(ret);
1558
18.7k
    }
1559
1560
4.50k
    *out = buf;
1561
4.50k
    return(ret);
1562
23.2k
}
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
22.9k
                            xmlCharEncodingHandler *encoder) {
1815
22.9k
    xmlOutputBufferPtr ret;
1816
1817
22.9k
    if (buffer == NULL) {
1818
136
        return(NULL);
1819
136
    }
1820
1821
22.8k
    ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
1822
22.8k
                                  encoder);
1823
1824
22.8k
    return(ret);
1825
22.9k
}
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
17.5k
xmlOutputBufferGetContent(xmlOutputBuffer *out) {
1835
17.5k
    if ((out == NULL) || (out->buffer == NULL) || ((out->encoder != NULL) && (out->conv == NULL)) || (out->error != 0))
1836
198
        return(NULL);
1837
1838
17.3k
    if (out->encoder != NULL)
1839
0
        return(xmlBufContent(out->conv));
1840
1841
17.3k
    return(xmlBufContent(out->buffer));
1842
17.3k
}
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
8.85k
xmlOutputBufferGetSize(xmlOutputBuffer *out) {
1852
8.85k
    if ((out == NULL) || (out->buffer == NULL) || ((out->encoder != NULL) && (out->conv == NULL)) || (out->error != 0))
1853
0
        return(0);
1854
1855
8.85k
    if (out->encoder != NULL)
1856
0
        return(xmlBufUse(out->conv));
1857
1858
8.85k
    return(xmlBufUse(out->buffer));
1859
8.85k
}
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
696k
xmlMemRead(void *vctxt, char *buf, int size) {
1909
696k
    xmlMemIOCtxt *ctxt = vctxt;
1910
1911
696k
    if ((size_t) size > ctxt->size)
1912
287k
        size = ctxt->size;
1913
1914
696k
    memcpy(buf, ctxt->cur, size);
1915
696k
    ctxt->cur += size;
1916
696k
    ctxt->size -= size;
1917
1918
696k
    return size;
1919
696k
}
1920
1921
static int
1922
146k
xmlMemClose(void *vctxt) {
1923
146k
    xmlMemIOCtxt *ctxt = vctxt;
1924
1925
146k
    xmlFree(ctxt);
1926
146k
    return(0);
1927
146k
}
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
853k
                        xmlParserInputFlags flags, xmlCharEncoding enc) {
1941
853k
    xmlParserInputBufferPtr ret;
1942
1943
853k
    if ((flags & XML_INPUT_BUF_STATIC) &&
1944
817k
        ((flags & XML_INPUT_BUF_ZERO_TERMINATED) == 0)) {
1945
146k
        xmlMemIOCtxt *ctxt;
1946
1947
        /*
1948
         * Static buffer without zero terminator.
1949
         * Stream memory to avoid a copy.
1950
         */
1951
146k
        ret = xmlAllocParserInputBuffer(enc);
1952
146k
        if (ret == NULL)
1953
27
            return(NULL);
1954
1955
146k
        ctxt = xmlMalloc(sizeof(*ctxt));
1956
146k
        if (ctxt == NULL) {
1957
17
            xmlFreeParserInputBuffer(ret);
1958
17
            return(NULL);
1959
17
        }
1960
1961
146k
        ctxt->cur = mem;
1962
146k
        ctxt->size = size;
1963
1964
146k
        ret->context = ctxt;
1965
146k
        ret->readcallback = xmlMemRead;
1966
146k
        ret->closecallback = xmlMemClose;
1967
707k
    } else {
1968
707k
        ret = xmlMalloc(sizeof(*ret));
1969
707k
        if (ret == NULL)
1970
95
            return(NULL);
1971
707k
        memset(ret, 0, sizeof(xmlParserInputBuffer));
1972
707k
        ret->compressed = -1;
1973
1974
707k
        ret->buffer = xmlBufCreateMem((const xmlChar *) mem, size,
1975
707k
                                      (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1976
707k
        if (ret->buffer == NULL) {
1977
80
            xmlFree(ret);
1978
80
            return(NULL);
1979
80
        }
1980
707k
    }
1981
1982
853k
    return(ret);
1983
853k
}
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
35.6k
xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
2006
35.6k
    if ((mem == NULL) || (size < 0))
2007
0
        return(NULL);
2008
2009
35.6k
    return(xmlNewInputBufferMemory(mem, size, 0, enc));
2010
35.6k
}
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
347k
xmlNewInputBufferString(const char *str, xmlParserInputFlags flags) {
2050
347k
    xmlParserInputBufferPtr ret;
2051
2052
347k
    ret = xmlMalloc(sizeof(*ret));
2053
347k
    if (ret == NULL)
2054
59
  return(NULL);
2055
347k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
2056
347k
    ret->compressed = -1;
2057
2058
347k
    ret->buffer = xmlBufCreateMem((const xmlChar *) str, strlen(str),
2059
347k
                                  (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
2060
347k
    if (ret->buffer == NULL) {
2061
50
        xmlFree(ret);
2062
50
  return(NULL);
2063
50
    }
2064
2065
347k
    return(ret);
2066
347k
}
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
1
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandler *encoder) {
2081
1
    xmlOutputBufferPtr ret;
2082
2083
1
    if (fd < 0) {
2084
0
        return(NULL);
2085
0
    }
2086
2087
1
    ret = xmlAllocOutputBuffer(encoder);
2088
1
    if (ret != NULL) {
2089
1
        xmlFdIOCtxt *fdctxt;
2090
2091
1
        fdctxt = xmlMalloc(sizeof(*fdctxt));
2092
1
        if (fdctxt == NULL) {
2093
0
            return(NULL);
2094
0
        }
2095
1
        fdctxt->fd = fd;
2096
2097
1
        ret->context = fdctxt;
2098
1
  ret->writecallback = xmlFdWrite;
2099
1
        ret->closecallback = xmlFdFree;
2100
1
    }
2101
2102
1
    return(ret);
2103
1
}
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
1
   xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
2125
1
    xmlParserInputBufferPtr ret;
2126
2127
1
    if (ioread == NULL) return(NULL);
2128
2129
1
    ret = xmlAllocParserInputBuffer(enc);
2130
1
    if (ret != NULL) {
2131
1
        ret->context = (void *) ioctx;
2132
1
  ret->readcallback = ioread;
2133
1
  ret->closecallback = ioclose;
2134
1
    }
2135
2136
1
    return(ret);
2137
1
}
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
56.9k
   xmlCharEncodingHandler *encoder) {
2156
56.9k
    xmlOutputBufferPtr ret;
2157
2158
56.9k
    if (iowrite == NULL) {
2159
0
        return(NULL);
2160
0
    }
2161
2162
56.9k
    ret = xmlAllocOutputBuffer(encoder);
2163
56.9k
    if (ret != NULL) {
2164
56.6k
        ret->context = (void *) ioctx;
2165
56.6k
  ret->writecallback = iowrite;
2166
56.6k
  ret->closecallback = ioclose;
2167
56.6k
    }
2168
2169
56.9k
    return(ret);
2170
56.9k
}
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
3.90M
                   int len, const char *buf) {
2232
3.90M
    size_t nbchars = 0;
2233
3.90M
    int ret;
2234
2235
3.90M
    if (len < 0) return(0);
2236
3.90M
    if ((in == NULL) || (in->error)) return(-1);
2237
3.90M
    if (in->encoder != NULL) {
2238
        /*
2239
   * Store the data in the incoming raw buffer
2240
   */
2241
1.94M
        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.94M
  ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
2249
1.94M
  if (ret != 0) {
2250
3
            in->error = XML_ERR_NO_MEMORY;
2251
3
      return(-1);
2252
3
        }
2253
2254
  /*
2255
   * convert as much as possible to the parser reading buffer.
2256
   */
2257
1.94M
        nbchars = SIZE_MAX;
2258
1.94M
  if (xmlCharEncInput(in, &nbchars, /* flush */ 0) !=
2259
1.94M
            XML_ENC_ERR_SUCCESS)
2260
138
            return(-1);
2261
1.94M
        if (nbchars > INT_MAX)
2262
0
            nbchars = INT_MAX;
2263
1.96M
    } else {
2264
1.96M
  nbchars = len;
2265
1.96M
        ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
2266
1.96M
  if (ret != 0) {
2267
7
            in->error = XML_ERR_NO_MEMORY;
2268
7
      return(-1);
2269
7
        }
2270
1.96M
    }
2271
3.90M
    return(nbchars);
2272
3.90M
}
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
8.25M
      int len ATTRIBUTE_UNUSED) {
2282
8.25M
    return(0);
2283
8.25M
}
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
12.8M
xmlParserInputBufferGrow(xmlParserInputBuffer *in, int len) {
2299
12.8M
    int res = 0;
2300
2301
12.8M
    if ((in == NULL) || (in->error))
2302
12.4k
        return(-1);
2303
2304
12.8M
    if (len < MINLEN)
2305
12.4M
        len = MINLEN;
2306
2307
    /*
2308
     * Call the read method for this I/O type.
2309
     */
2310
12.8M
    if (in->readcallback != NULL) {
2311
9.20M
        xmlBufPtr buf;
2312
2313
9.20M
        if (in->encoder == NULL) {
2314
8.42M
            buf = in->buffer;
2315
8.42M
        } else {
2316
            /*
2317
             * Some users only set 'encoder' and expect us to create
2318
             * the raw buffer lazily.
2319
             */
2320
775k
            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
775k
            buf = in->raw;
2328
775k
        }
2329
2330
9.20M
        if (xmlBufGrow(buf, len) < 0) {
2331
22
            in->error = XML_ERR_NO_MEMORY;
2332
22
            return(-1);
2333
22
        }
2334
2335
9.20M
  res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
2336
9.20M
  if (res <= 0)
2337
8.39M
      in->readcallback = endOfInput;
2338
9.20M
        if (res < 0) {
2339
2.17k
            if (res == -1)
2340
1
                in->error = XML_IO_UNKNOWN;
2341
2.17k
            else
2342
2.17k
                in->error = -res;
2343
2.17k
            return(-1);
2344
2.17k
        }
2345
2346
9.20M
        if (xmlBufAddLen(buf, res) < 0) {
2347
0
            in->error = XML_ERR_NO_MEMORY;
2348
0
            return(-1);
2349
0
        }
2350
9.20M
    }
2351
2352
    /*
2353
     * Handle encoding.
2354
     */
2355
12.8M
    if (in->encoder != NULL) {
2356
4.17M
        size_t sizeOut;
2357
2358
        /*
2359
         * Don't convert whole buffer when reading from memory.
2360
         */
2361
4.17M
        if (in->readcallback == NULL)
2362
3.39M
            sizeOut = len;
2363
775k
        else
2364
775k
            sizeOut = SIZE_MAX;
2365
2366
4.17M
  if (xmlCharEncInput(in, &sizeOut, /* flush */ 0) !=
2367
4.17M
            XML_ENC_ERR_SUCCESS)
2368
8.81k
      return(-1);
2369
4.16M
        res = sizeOut;
2370
4.16M
    }
2371
12.8M
    return(res);
2372
12.8M
}
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
66.1k
xmlParserInputBufferRead(xmlParserInputBuffer *in, int len) {
2386
66.1k
    return(xmlParserInputBufferGrow(in, len));
2387
66.1k
}
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
353M
xmlOutputBufferWrite(xmlOutputBuffer *out, int len, const char *data) {
2404
353M
    xmlBufPtr buf = NULL;
2405
353M
    size_t written = 0;
2406
353M
    int ret;
2407
2408
353M
    if ((out == NULL) || (out->error))
2409
653k
        return(-1);
2410
352M
    if (len < 0)
2411
0
        return(0);
2412
2413
352M
    ret = xmlBufAdd(out->buffer, (const xmlChar *) data, len);
2414
352M
    if (ret != 0) {
2415
63
        out->error = XML_ERR_NO_MEMORY;
2416
63
        return(-1);
2417
63
    }
2418
2419
    /*
2420
     * first handle encoding stuff.
2421
     */
2422
352M
    if (out->encoder != NULL) {
2423
        /*
2424
         * Store the data in the incoming raw buffer
2425
         */
2426
29.2M
        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
29.2M
        if (xmlBufUse(out->buffer) < 256) {
2438
28.1M
            ret = 0;
2439
28.1M
        } else {
2440
1.12M
            ret = xmlCharEncOutput(out, 0);
2441
1.12M
            if (ret < 0)
2442
565
                return(-1);
2443
1.12M
        }
2444
2445
29.2M
        if (out->writecallback)
2446
391k
            buf = out->conv;
2447
28.8M
        else
2448
28.8M
            written = ret;
2449
323M
    } else {
2450
323M
        if (out->writecallback)
2451
84.3M
            buf = out->buffer;
2452
239M
        else
2453
239M
            written = len;
2454
323M
    }
2455
2456
352M
    if ((buf != NULL) && (out->writecallback)) {
2457
        /*
2458
         * second write the stuff to the I/O channel
2459
         */
2460
84.8M
        while (1) {
2461
84.8M
            size_t nbchars = xmlBufUse(buf);
2462
2463
84.8M
            if (nbchars < MINLEN)
2464
84.6M
                break;
2465
2466
147k
            if (nbchars >= INT_MAX) {
2467
0
                out->error = XML_ERR_INTERNAL_ERROR;
2468
0
                return(-1);
2469
0
            }
2470
2471
147k
            ret = out->writecallback(out->context,
2472
147k
                       (const char *)xmlBufContent(buf), nbchars);
2473
147k
            if (ret < 0) {
2474
9
                out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2475
9
                return(-1);
2476
9
            }
2477
147k
            if ((ret == 0) || ((size_t) ret > nbchars)) {
2478
0
                out->error = XML_ERR_INTERNAL_ERROR;
2479
0
                return(-1);
2480
0
            }
2481
2482
147k
            xmlBufShrink(buf, ret);
2483
147k
            written += ret;
2484
147k
            if (out->written > INT_MAX - ret)
2485
0
                out->written = INT_MAX;
2486
147k
            else
2487
147k
                out->written += ret;
2488
147k
        }
2489
84.6M
    }
2490
2491
352M
    return(written <= INT_MAX ? written : INT_MAX);
2492
352M
}
2493
2494
/**
2495
 * Write the content of the string in the output I/O buffer
2496
 * This routine escapes the characters and then handle the I18N
2497
 * transcoding from internal UTF-8
2498
 * The buffer is lossless, i.e. will store in case of partial
2499
 * or delayed writes.
2500
 *
2501
 * @param out  a buffered parser output
2502
 * @param str  a zero terminated UTF-8 string
2503
 * @param escaping  an optional escaping function (or NULL)
2504
 * @returns the number of chars immediately written, or -1
2505
 *         in case of error.
2506
 */
2507
int
2508
xmlOutputBufferWriteEscape(xmlOutputBuffer *out, const xmlChar *str,
2509
0
                           xmlCharEncodingOutputFunc escaping) {
2510
0
    int ret;
2511
0
    int written = 0;
2512
0
    size_t len;
2513
2514
0
    if ((out == NULL) || (out->error) || (str == NULL))
2515
0
        return(-1);
2516
2517
0
    len = strlen((const char *) str);
2518
0
    if (len >= INT_MAX) {
2519
0
        out->error = XML_ERR_RESOURCE_LIMIT;
2520
0
        return(-1);
2521
0
    }
2522
2523
0
    if (escaping == NULL) {
2524
0
        char *escaped = (char *) xmlEscapeText(str, 0);
2525
2526
0
        if (escaped == NULL) {
2527
0
            out->error = XML_ERR_NO_MEMORY;
2528
0
            return(-1);
2529
0
        }
2530
2531
0
        len = strlen(escaped);
2532
0
        if (len >= INT_MAX) {
2533
0
            out->error = XML_ERR_RESOURCE_LIMIT;
2534
0
            return(-1);
2535
0
        }
2536
2537
0
        ret = xmlOutputBufferWrite(out, len, escaped);
2538
2539
0
        xmlFree(escaped);
2540
0
        return(ret);
2541
0
    }
2542
2543
0
    while (len > 0) {
2544
0
        xmlChar buf[1024];
2545
0
        int c_out;
2546
0
        int c_in;
2547
2548
0
  c_out = 1024;
2549
0
  c_in = len;
2550
2551
0
        ret = escaping(buf, &c_out, str, &c_in);
2552
0
        if (ret < 0) {
2553
0
            out->error = XML_ERR_NO_MEMORY;
2554
0
            return(-1);
2555
0
        }
2556
0
        str += c_in;
2557
0
        len -= c_in;
2558
2559
0
        ret = xmlOutputBufferWrite(out, c_out, (char *) buf);
2560
0
        if (ret < 0)
2561
0
            return(ret);
2562
0
        written += ret;
2563
0
    }
2564
2565
0
    return(written);
2566
0
}
2567
2568
/**
2569
 * Write the content of the string in the output I/O buffer
2570
 * This routine handle the I18N transcoding from internal UTF-8
2571
 * The buffer is lossless, i.e. will store in case of partial
2572
 * or delayed writes.
2573
 *
2574
 * @param out  a buffered parser output
2575
 * @param str  a zero terminated C string
2576
 * @returns the number of chars immediately written, or -1
2577
 *         in case of error.
2578
 */
2579
int
2580
7.63M
xmlOutputBufferWriteString(xmlOutputBuffer *out, const char *str) {
2581
7.63M
    int len;
2582
2583
7.63M
    if ((out == NULL) || (out->error)) return(-1);
2584
7.40M
    if (str == NULL)
2585
8.97k
        return(-1);
2586
7.39M
    len = strlen(str);
2587
2588
7.39M
    if (len > 0)
2589
6.94M
  return(xmlOutputBufferWrite(out, len, str));
2590
455k
    return(len);
2591
7.39M
}
2592
2593
/**
2594
 * Write a string surrounded by quotes to an output buffer.
2595
 *
2596
 * Uses double quotes if the string contains no double quotes.
2597
 * Otherwise, uses single quotes if the string contains no
2598
 * single quotes. Otherwise, uses double quotes and escapes
2599
 * double quotes.
2600
 *
2601
 * This should only be used to escape system IDs. Currently,
2602
 * we also use it for public IDs and original entity values.
2603
 *
2604
 * @param buf  output buffer
2605
 * @param string  the string to add
2606
 */
2607
void
2608
xmlOutputBufferWriteQuotedString(xmlOutputBuffer *buf,
2609
118k
                                 const xmlChar *string) {
2610
118k
    const xmlChar *cur, *base;
2611
2612
118k
    if ((buf == NULL) || (buf->error))
2613
401
        return;
2614
2615
118k
    if (xmlStrchr(string, '\"')) {
2616
13.2k
        if (xmlStrchr(string, '\'')) {
2617
2.47k
      xmlOutputBufferWrite(buf, 1, "\"");
2618
2.47k
            base = cur = string;
2619
915k
            while(*cur != 0){
2620
912k
                if(*cur == '"'){
2621
40.6k
                    if (base != cur)
2622
35.6k
                        xmlOutputBufferWrite(buf, cur - base,
2623
35.6k
                                             (const char *) base);
2624
40.6k
                    xmlOutputBufferWrite(buf, 6, "&quot;");
2625
40.6k
                    cur++;
2626
40.6k
                    base = cur;
2627
40.6k
                }
2628
872k
                else {
2629
872k
                    cur++;
2630
872k
                }
2631
912k
            }
2632
2.47k
            if (base != cur)
2633
2.21k
                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
2634
2.47k
      xmlOutputBufferWrite(buf, 1, "\"");
2635
2.47k
  }
2636
10.7k
        else{
2637
10.7k
      xmlOutputBufferWrite(buf, 1, "'");
2638
10.7k
            xmlOutputBufferWriteString(buf, (const char *) string);
2639
10.7k
      xmlOutputBufferWrite(buf, 1, "'");
2640
10.7k
        }
2641
105k
    } else {
2642
105k
        xmlOutputBufferWrite(buf, 1, "\"");
2643
105k
        xmlOutputBufferWriteString(buf, (const char *) string);
2644
105k
        xmlOutputBufferWrite(buf, 1, "\"");
2645
105k
    }
2646
118k
}
2647
2648
/**
2649
 * flushes the output I/O channel
2650
 *
2651
 * @param out  a buffered output
2652
 * @returns the number of byte written or -1 in case of error.
2653
 */
2654
int
2655
103k
xmlOutputBufferFlush(xmlOutputBuffer *out) {
2656
103k
    int nbchars = 0, ret = 0;
2657
2658
103k
    if ((out == NULL) || (out->error)) return(-1);
2659
    /*
2660
     * first handle encoding stuff.
2661
     */
2662
98.8k
    if ((out->conv != NULL) && (out->encoder != NULL)) {
2663
  /*
2664
   * convert as much as possible to the parser output buffer.
2665
   */
2666
29.5k
  do {
2667
29.5k
      nbchars = xmlCharEncOutput(out, 0);
2668
29.5k
      if (nbchars < 0)
2669
1.92k
    return(-1);
2670
29.5k
  } while (nbchars);
2671
14.4k
    }
2672
2673
    /*
2674
     * second flush the stuff to the I/O channel
2675
     */
2676
96.8k
    if ((out->conv != NULL) && (out->encoder != NULL) &&
2677
12.5k
  (out->writecallback != NULL)) {
2678
5.32k
        size_t bufsize = xmlBufUse(out->conv);
2679
5.32k
        if (bufsize >= INT_MAX) {
2680
0
            out->error = XML_ERR_INTERNAL_ERROR;
2681
0
            return(-1);
2682
0
        }
2683
5.32k
  ret = out->writecallback(out->context,
2684
5.32k
                                 (const char *)xmlBufContent(out->conv),
2685
5.32k
                                 bufsize);
2686
5.32k
  if (ret >= 0)
2687
5.31k
      xmlBufShrink(out->conv, ret);
2688
91.5k
    } else if (out->writecallback != NULL) {
2689
61.0k
        size_t bufsize = xmlBufUse(out->buffer);
2690
61.0k
        if (bufsize >= INT_MAX) {
2691
0
            out->error = XML_ERR_INTERNAL_ERROR;
2692
0
            return(-1);
2693
0
        }
2694
61.0k
  ret = out->writecallback(out->context,
2695
61.0k
                                 (const char *)xmlBufContent(out->buffer),
2696
61.0k
                                 bufsize);
2697
61.0k
  if (ret >= 0)
2698
61.0k
      xmlBufShrink(out->buffer, ret);
2699
61.0k
    }
2700
96.8k
    if (ret < 0) {
2701
37
        out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2702
37
  return(ret);
2703
37
    }
2704
96.8k
    if (out->written > INT_MAX - ret)
2705
0
        out->written = INT_MAX;
2706
96.8k
    else
2707
96.8k
        out->written += ret;
2708
2709
96.8k
    return(ret);
2710
96.8k
}
2711
#endif /* LIBXML_OUTPUT_ENABLED */
2712
2713
/**
2714
 * lookup the directory for that file
2715
 *
2716
 * @param filename  the path to a file
2717
 * @returns a new allocated string containing the directory, or NULL.
2718
 */
2719
char *
2720
596k
xmlParserGetDirectory(const char *filename) {
2721
596k
    char *ret = NULL;
2722
596k
    char dir[1024];
2723
596k
    char *cur;
2724
2725
596k
    if (filename == NULL) return(NULL);
2726
2727
#if defined(LIBXML_WINPATH_ENABLED)
2728
#   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
2729
#else
2730
6.67M
#   define IS_XMLPGD_SEP(ch) (ch=='/')
2731
596k
#endif
2732
2733
596k
    strncpy(dir, filename, 1023);
2734
596k
    dir[1023] = 0;
2735
596k
    cur = &dir[strlen(dir)];
2736
6.61M
    while (cur > dir) {
2737
6.07M
         if (IS_XMLPGD_SEP(*cur)) break;
2738
6.02M
   cur --;
2739
6.02M
    }
2740
596k
    if (IS_XMLPGD_SEP(*cur)) {
2741
59.1k
        if (cur == dir) dir[1] = 0;
2742
55.8k
  else *cur = 0;
2743
59.1k
  ret = xmlMemStrdup(dir);
2744
537k
    } else {
2745
537k
        ret = xmlMemStrdup(".");
2746
537k
    }
2747
596k
    return(ret);
2748
596k
#undef IS_XMLPGD_SEP
2749
596k
}
2750
2751
/**
2752
 * Like #xmlCheckFilename but handles file URIs.
2753
 *
2754
 * @deprecated Internal function, don't use.
2755
 *
2756
 * @param filename  the path to check
2757
 * @returns 0, 1, or 2.
2758
 */
2759
int
2760
0
xmlNoNetExists(const char *filename) {
2761
0
    char *fromUri;
2762
0
    int ret;
2763
2764
0
    if (filename == NULL)
2765
0
  return(0);
2766
2767
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
2768
0
        return(0);
2769
2770
0
    if (fromUri != NULL)
2771
0
        filename = fromUri;
2772
2773
0
    ret =  xmlCheckFilename(filename);
2774
2775
0
    xmlFree(fromUri);
2776
0
    return(ret);
2777
0
}
2778
2779
/************************************************************************
2780
 *                  *
2781
 *      Input/output callbacks        *
2782
 *                  *
2783
 ************************************************************************/
2784
2785
/**
2786
 * Initialize callback tables.
2787
 */
2788
void
2789
xmlInitIOCallbacks(void)
2790
342
{
2791
342
    xmlInputCallbackNr = 1;
2792
342
    xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2793
2794
342
#ifdef LIBXML_OUTPUT_ENABLED
2795
342
    xmlOutputCallbackNr = 1;
2796
342
    xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2797
342
#endif
2798
342
}
2799
2800
/**
2801
 * Register a new set of I/O callback for handling parser input.
2802
 *
2803
 * @deprecated Use #xmlCtxtSetResourceLoader or similar functions.
2804
 *
2805
 * @param matchFunc  the xmlInputMatchCallback
2806
 * @param openFunc  the xmlInputOpenCallback
2807
 * @param readFunc  the xmlInputReadCallback
2808
 * @param closeFunc  the xmlInputCloseCallback
2809
 * @returns the registered handler number or -1 in case of error
2810
 */
2811
int
2812
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2813
  xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2814
0
  xmlInputCloseCallback closeFunc) {
2815
0
    xmlInitParser();
2816
2817
0
    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2818
0
  return(-1);
2819
0
    }
2820
0
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2821
0
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2822
0
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2823
0
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2824
0
    return(xmlInputCallbackNr++);
2825
0
}
2826
2827
/**
2828
 * Registers the default compiled-in I/O handlers.
2829
 */
2830
void
2831
0
xmlRegisterDefaultInputCallbacks(void) {
2832
0
    xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2833
0
}
2834
2835
/**
2836
 * Clear the top input callback from the input stack. this includes the
2837
 * compiled-in I/O.
2838
 *
2839
 * @returns the number of input callback registered or -1 in case of error.
2840
 */
2841
int
2842
xmlPopInputCallbacks(void)
2843
0
{
2844
0
    xmlInitParser();
2845
2846
0
    if (xmlInputCallbackNr <= 0)
2847
0
        return(-1);
2848
2849
0
    xmlInputCallbackNr--;
2850
2851
0
    return(xmlInputCallbackNr);
2852
0
}
2853
2854
/**
2855
 * clears the entire input callback table. this includes the
2856
 * compiled-in I/O.
2857
 */
2858
void
2859
xmlCleanupInputCallbacks(void)
2860
0
{
2861
0
    xmlInitParser();
2862
2863
0
    xmlInputCallbackNr = 0;
2864
0
}
2865
2866
#ifdef LIBXML_OUTPUT_ENABLED
2867
/**
2868
 * Register a new set of I/O callback for handling output.
2869
 *
2870
 * @param matchFunc  the xmlOutputMatchCallback
2871
 * @param openFunc  the xmlOutputOpenCallback
2872
 * @param writeFunc  the xmlOutputWriteCallback
2873
 * @param closeFunc  the xmlOutputCloseCallback
2874
 * @returns the registered handler number or -1 in case of error
2875
 */
2876
int
2877
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2878
  xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2879
0
  xmlOutputCloseCallback closeFunc) {
2880
0
    xmlInitParser();
2881
2882
0
    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2883
0
  return(-1);
2884
0
    }
2885
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2886
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2887
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2888
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2889
0
    return(xmlOutputCallbackNr++);
2890
0
}
2891
2892
/**
2893
 * Registers the default compiled-in I/O handlers.
2894
 */
2895
void
2896
0
xmlRegisterDefaultOutputCallbacks (void) {
2897
0
    xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2898
0
}
2899
2900
/**
2901
 * Remove the top output callbacks from the output stack. This includes the
2902
 * compiled-in I/O.
2903
 *
2904
 * @returns the number of output callback registered or -1 in case of error.
2905
 */
2906
int
2907
xmlPopOutputCallbacks(void)
2908
0
{
2909
0
    xmlInitParser();
2910
2911
0
    if (xmlOutputCallbackNr <= 0)
2912
0
        return(-1);
2913
2914
0
    xmlOutputCallbackNr--;
2915
2916
0
    return(xmlOutputCallbackNr);
2917
0
}
2918
2919
/**
2920
 * clears the entire output callback table. this includes the
2921
 * compiled-in I/O callbacks.
2922
 */
2923
void
2924
xmlCleanupOutputCallbacks(void)
2925
0
{
2926
0
    xmlInitParser();
2927
2928
0
    xmlOutputCallbackNr = 0;
2929
0
}
2930
#endif /* LIBXML_OUTPUT_ENABLED */
2931