Coverage Report

Created: 2025-11-16 09:57

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