Coverage Report

Created: 2025-10-13 06:43

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