Coverage Report

Created: 2025-12-29 06:16

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