Coverage Report

Created: 2024-02-25 06:19

/src/libxml2/xmlIO.c
Line
Count
Source (jump to first uncovered line)
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
26.3M
#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
xmlGzfileRead (void * context, char * buffer, int len) {
897
    int ret;
898
899
    ret = gzread((gzFile) context, &buffer[0], len);
900
    if (ret < 0) xmlIOErr(0, "gzread()");
901
    return(ret);
902
}
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
xmlGzfileWrite (void * context, const char * buffer, int len) {
917
    int ret;
918
919
    ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
920
    if (ret < 0) xmlIOErr(0, "gzwrite()");
921
    return(ret);
922
}
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
xmlGzfileClose (void * context) {
933
    int ret;
934
935
    ret =  (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
936
    if (ret < 0) xmlIOErr(0, "gzclose()");
937
    return(ret);
938
}
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
0
xmlIOHTTPMatch (const char *filename) {
1005
0
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
1006
0
  return(1);
1007
0
    return(0);
1008
0
}
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
0
xmlIOHTTPOpen (const char *filename) {
1022
0
    return(xmlNanoHTTPOpen(filename, NULL));
1023
0
}
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
0
{
1039
0
    return(NULL);
1040
0
}
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
0
xmlIOHTTPRead(void * context, char * buffer, int len) {
1057
0
    if ((buffer == NULL) || (len < 0)) return(-1);
1058
0
    return(xmlNanoHTTPRead(context, &buffer[0], len));
1059
0
}
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
0
xmlIOHTTPClose (void * context) {
1073
0
    xmlNanoHTTPClose(context);
1074
0
    return 0;
1075
0
}
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
0
#ifdef LIBXML_HTTP_ENABLED
1186
0
    if (xmlIOHTTPMatch(filename)) {
1187
0
        buf->context = xmlIOHTTPOpen(filename);
1188
1189
0
        if (buf->context != NULL) {
1190
0
            buf->readcallback = xmlIOHTTPRead;
1191
0
            buf->closecallback = xmlIOHTTPClose;
1192
0
            return(XML_ERR_OK);
1193
0
        }
1194
0
    }
1195
0
#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
#ifdef LIBXML_ZLIB_ENABLED
1228
    {
1229
        gzFile gzStream;
1230
1231
        ret = xmlFdOpen(filename, 0, &fd);
1232
        if (ret != XML_ERR_OK)
1233
            return(ret);
1234
1235
        gzStream = gzdopen(fd, "rb");
1236
1237
        if (gzStream == NULL) {
1238
            close(fd);
1239
        } else {
1240
            char buff4[4];
1241
1242
            if ((gzread(gzStream, buff4, 4) > 0) &&
1243
                (gzdirect(gzStream) == 0)) {
1244
                gzrewind(gzStream);
1245
1246
                buf->context = gzStream;
1247
                buf->readcallback = xmlGzfileRead;
1248
                buf->closecallback = xmlGzfileClose;
1249
                buf->compressed = 1;
1250
1251
                return(XML_ERR_OK);
1252
            }
1253
1254
            xmlGzfileClose(gzStream);
1255
        }
1256
    }
1257
#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
#ifdef LIBXML_ZLIB_ENABLED
1300
    if ((compression > 0) && (compression <= 9)) {
1301
        gzFile gzStream;
1302
        char mode[15];
1303
1304
        snprintf(mode, sizeof(mode), "wb%d", compression);
1305
        gzStream = gzdopen(fd, mode);
1306
1307
        if (gzStream == NULL) {
1308
            close(fd);
1309
            return(xmlIOErr(XML_IO_UNKNOWN, "gzdopen()"));
1310
        }
1311
1312
        buf->context = gzStream;
1313
        buf->writecallback = xmlGzfileWrite;
1314
        buf->closecallback = xmlGzfileClose;
1315
1316
        return(XML_ERR_OK);
1317
    }
1318
#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
98.4k
xmlAllocParserInputBuffer(xmlCharEncoding enc) {
1341
98.4k
    xmlParserInputBufferPtr ret;
1342
1343
98.4k
    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1344
98.4k
    if (ret == NULL) {
1345
14
  return(NULL);
1346
14
    }
1347
98.4k
    memset(ret, 0, sizeof(xmlParserInputBuffer));
1348
98.4k
    ret->buffer = xmlBufCreateSize(2 * xmlDefaultBufferSize);
1349
98.4k
    if (ret->buffer == NULL) {
1350
20
        xmlFree(ret);
1351
20
  return(NULL);
1352
20
    }
1353
98.4k
    xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
1354
98.4k
    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
98.4k
    if (ret->encoder != NULL)
1362
0
        ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
1363
98.4k
    else
1364
98.4k
        ret->raw = NULL;
1365
98.4k
    ret->readcallback = NULL;
1366
98.4k
    ret->closecallback = NULL;
1367
98.4k
    ret->context = NULL;
1368
98.4k
    ret->compressed = -1;
1369
98.4k
    ret->rawconsumed = 0;
1370
1371
98.4k
    return(ret);
1372
98.4k
}
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
1.99k
xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
1385
1.99k
    xmlOutputBufferPtr ret;
1386
1387
1.99k
    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
1388
1.99k
    if (ret == NULL) {
1389
34
  return(NULL);
1390
34
    }
1391
1.95k
    memset(ret, 0, sizeof(xmlOutputBuffer));
1392
1.95k
    ret->buffer = xmlBufCreate();
1393
1.95k
    if (ret->buffer == NULL) {
1394
7
        xmlFree(ret);
1395
7
  return(NULL);
1396
7
    }
1397
1.95k
    xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
1398
1399
1.95k
    ret->encoder = encoder;
1400
1.95k
    if (encoder != NULL) {
1401
108
        ret->conv = xmlBufCreateSize(4000);
1402
108
  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
108
  xmlCharEncOutput(ret, 1);
1412
108
    } else
1413
1.84k
        ret->conv = NULL;
1414
1.95k
    ret->writecallback = NULL;
1415
1.95k
    ret->closecallback = NULL;
1416
1.95k
    ret->context = NULL;
1417
1.95k
    ret->written = 0;
1418
1419
1.95k
    return(ret);
1420
1.95k
}
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
98.4k
xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1484
98.4k
    if (in == NULL) return;
1485
1486
98.4k
    if (in->raw) {
1487
36.6k
        xmlBufFree(in->raw);
1488
36.6k
  in->raw = NULL;
1489
36.6k
    }
1490
98.4k
    if (in->encoder != NULL) {
1491
36.6k
        xmlCharEncCloseFunc(in->encoder);
1492
36.6k
    }
1493
98.4k
    if (in->closecallback != NULL) {
1494
98.4k
  in->closecallback(in->context);
1495
98.4k
    }
1496
98.4k
    if (in->buffer != NULL) {
1497
98.4k
        xmlBufFree(in->buffer);
1498
98.4k
  in->buffer = NULL;
1499
98.4k
    }
1500
1501
98.4k
    xmlFree(in);
1502
98.4k
}
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
1.95k
{
1518
1.95k
    int ret;
1519
1520
1.95k
    if (out == NULL)
1521
0
        return (-1);
1522
1523
1.95k
    if (out->writecallback != NULL)
1524
0
        xmlOutputBufferFlush(out);
1525
1526
1.95k
    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
1.95k
    if (out->error != XML_ERR_OK)
1538
19
        ret = -out->error;
1539
1.93k
    else
1540
1.93k
        ret = out->written;
1541
1542
1.95k
    if (out->conv) {
1543
108
        xmlBufFree(out->conv);
1544
108
        out->conv = NULL;
1545
108
    }
1546
1.95k
    if (out->encoder != NULL) {
1547
108
        xmlCharEncCloseFunc(out->encoder);
1548
108
    }
1549
1.95k
    if (out->buffer != NULL) {
1550
1.95k
        xmlBufFree(out->buffer);
1551
1.95k
        out->buffer = NULL;
1552
1.95k
    }
1553
1554
1.95k
    xmlFree(out);
1555
1556
1.95k
    return(ret);
1557
1.95k
}
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
 * Returns an xmlParserErrors code.
1655
 */
1656
int
1657
xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc,
1658
0
                                       xmlParserInputBufferPtr *out) {
1659
0
    if (xmlParserInputBufferCreateFilenameValue != NULL) {
1660
0
        *out = xmlParserInputBufferCreateFilenameValue(URI, enc);
1661
1662
0
        if (*out == NULL)
1663
0
            return(XML_IO_ENOENT);
1664
0
        return(XML_ERR_OK);
1665
0
    }
1666
1667
0
    return(xmlParserInputBufferCreateFilenameInt(URI, enc, out));
1668
0
}
1669
1670
#ifdef LIBXML_OUTPUT_ENABLED
1671
xmlOutputBufferPtr
1672
__xmlOutputBufferCreateFilename(const char *URI,
1673
                              xmlCharEncodingHandlerPtr encoder,
1674
0
                              int compression) {
1675
0
    xmlOutputBufferPtr ret;
1676
0
    xmlURIPtr puri;
1677
0
    int i = 0;
1678
0
    char *unescaped = NULL;
1679
1680
0
    if (URI == NULL)
1681
0
        return(NULL);
1682
1683
0
    puri = xmlParseURI(URI);
1684
0
    if (puri != NULL) {
1685
        /*
1686
         * try to limit the damages of the URI unescaping code.
1687
         */
1688
0
        if (puri->scheme == NULL) {
1689
0
            unescaped = xmlURIUnescapeString(URI, 0, NULL);
1690
0
             if (unescaped == NULL) {
1691
0
                 xmlFreeURI(puri);
1692
0
                 return(NULL);
1693
0
             }
1694
0
             URI = unescaped;
1695
0
        }
1696
0
        xmlFreeURI(puri);
1697
0
    }
1698
1699
    /*
1700
     * Allocate the Output buffer front-end.
1701
     */
1702
0
    ret = xmlAllocOutputBufferInternal(encoder);
1703
0
    if (ret == NULL) {
1704
0
        xmlFree(unescaped);
1705
0
        return(NULL);
1706
0
    }
1707
1708
    /*
1709
     * Try to find one of the output accept method accepting that scheme
1710
     * Go in reverse to give precedence to user defined handlers.
1711
     */
1712
0
    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
1713
0
        xmlOutputCallback *cb = &xmlOutputCallbackTable[i];
1714
0
        int code;
1715
1716
0
        if (cb->matchcallback == xmlIODefaultMatch) {
1717
0
            code = xmlOutputDefaultOpen(ret, URI, compression);
1718
            /* TODO: Handle other errors */
1719
0
            if (code == XML_ERR_OK)
1720
0
                break;
1721
0
        } else if ((cb->matchcallback != NULL) &&
1722
0
                   (cb->matchcallback(URI) != 0)) {
1723
0
            ret->context = cb->opencallback(URI);
1724
0
            if (ret->context != NULL) {
1725
0
                ret->writecallback = cb->writecallback;
1726
0
                ret->closecallback = cb->closecallback;
1727
0
                break;
1728
0
            }
1729
0
        }
1730
0
    }
1731
1732
0
    if (ret->context == NULL) {
1733
0
        xmlOutputBufferClose(ret);
1734
0
  ret = NULL;
1735
0
    }
1736
1737
0
    xmlFree(unescaped);
1738
0
    return(ret);
1739
0
}
1740
1741
/**
1742
 * xmlOutputBufferCreateFilename:
1743
 * @URI:  a C string containing the URI or filename
1744
 * @encoder:  the encoding converter or NULL
1745
 * @compression:  the compression ration (0 none, 9 max).
1746
 *
1747
 * Create a buffered  output for the progressive saving of a file
1748
 * If filename is "-' then we use stdout as the output.
1749
 * Automatic support for ZLIB/Compress compressed document is provided
1750
 * by default if found at compile-time.
1751
 * TODO: currently if compression is set, the library only support
1752
 *       writing to a local file.
1753
 *
1754
 * Returns the new output or NULL
1755
 */
1756
xmlOutputBufferPtr
1757
xmlOutputBufferCreateFilename(const char *URI,
1758
                              xmlCharEncodingHandlerPtr encoder,
1759
0
                              int compression ATTRIBUTE_UNUSED) {
1760
0
    if ((xmlOutputBufferCreateFilenameValue)) {
1761
0
    return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
1762
0
  }
1763
0
  return __xmlOutputBufferCreateFilename(URI, encoder, compression);
1764
0
}
1765
#endif /* LIBXML_OUTPUT_ENABLED */
1766
1767
/**
1768
 * xmlParserInputBufferCreateFile:
1769
 * @file:  a FILE*
1770
 * @enc:  the charset encoding if known (deprecated)
1771
 *
1772
 * Create a buffered parser input for the progressive parsing of a FILE *
1773
 * buffered C I/O
1774
 *
1775
 * The encoding argument is deprecated and should be set to
1776
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1777
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1778
 *
1779
 * Returns the new parser input or NULL
1780
 */
1781
xmlParserInputBufferPtr
1782
0
xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
1783
0
    xmlParserInputBufferPtr ret;
1784
1785
0
    if (file == NULL) return(NULL);
1786
1787
0
    ret = xmlAllocParserInputBuffer(enc);
1788
0
    if (ret != NULL) {
1789
0
        ret->context = file;
1790
0
  ret->readcallback = xmlFileRead;
1791
0
  ret->closecallback = NULL;
1792
0
    }
1793
1794
0
    return(ret);
1795
0
}
1796
1797
#ifdef LIBXML_OUTPUT_ENABLED
1798
/**
1799
 * xmlOutputBufferCreateFile:
1800
 * @file:  a FILE*
1801
 * @encoder:  the encoding converter or NULL
1802
 *
1803
 * Create a buffered output for the progressive saving to a FILE *
1804
 * buffered C I/O
1805
 *
1806
 * Returns the new parser output or NULL
1807
 */
1808
xmlOutputBufferPtr
1809
0
xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
1810
0
    xmlOutputBufferPtr ret;
1811
1812
0
    if (file == NULL) return(NULL);
1813
1814
0
    ret = xmlAllocOutputBufferInternal(encoder);
1815
0
    if (ret != NULL) {
1816
0
        ret->context = file;
1817
0
  ret->writecallback = xmlFileWrite;
1818
0
  ret->closecallback = xmlFileFlush;
1819
0
    }
1820
1821
0
    return(ret);
1822
0
}
1823
1824
/**
1825
 * xmlOutputBufferCreateBuffer:
1826
 * @buffer:  a xmlBufferPtr
1827
 * @encoder:  the encoding converter or NULL
1828
 *
1829
 * Create a buffered output for the progressive saving to a xmlBuffer
1830
 *
1831
 * Returns the new parser output or NULL
1832
 */
1833
xmlOutputBufferPtr
1834
xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
1835
0
                            xmlCharEncodingHandlerPtr encoder) {
1836
0
    xmlOutputBufferPtr ret;
1837
1838
0
    if (buffer == NULL) return(NULL);
1839
1840
0
    ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
1841
0
                                  encoder);
1842
1843
0
    return(ret);
1844
0
}
1845
1846
/**
1847
 * xmlOutputBufferGetContent:
1848
 * @out:  an xmlOutputBufferPtr
1849
 *
1850
 * Gives a pointer to the data currently held in the output buffer
1851
 *
1852
 * Returns a pointer to the data or NULL in case of error
1853
 */
1854
const xmlChar *
1855
0
xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
1856
0
    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1857
0
        return(NULL);
1858
1859
0
    return(xmlBufContent(out->buffer));
1860
0
}
1861
1862
/**
1863
 * xmlOutputBufferGetSize:
1864
 * @out:  an xmlOutputBufferPtr
1865
 *
1866
 * Gives the length of the data currently held in the output buffer
1867
 *
1868
 * Returns 0 in case or error or no data is held, the size otherwise
1869
 */
1870
size_t
1871
0
xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
1872
0
    if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1873
0
        return(0);
1874
1875
0
    return(xmlBufUse(out->buffer));
1876
0
}
1877
1878
1879
#endif /* LIBXML_OUTPUT_ENABLED */
1880
1881
/**
1882
 * xmlParserInputBufferCreateFd:
1883
 * @fd:  a file descriptor number
1884
 * @enc:  the charset encoding if known (deprecated)
1885
 *
1886
 * Create a buffered parser input for the progressive parsing for the input
1887
 * from a file descriptor
1888
 *
1889
 * The encoding argument is deprecated and should be set to
1890
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1891
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1892
 *
1893
 * Returns the new parser input or NULL
1894
 */
1895
xmlParserInputBufferPtr
1896
0
xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1897
0
    xmlParserInputBufferPtr ret;
1898
1899
0
    if (fd < 0) return(NULL);
1900
1901
0
    ret = xmlAllocParserInputBuffer(enc);
1902
0
    if (ret != NULL) {
1903
0
        ret->context = (void *) (ptrdiff_t) fd;
1904
0
  ret->readcallback = xmlFdRead;
1905
0
  ret->closecallback = xmlFdClose;
1906
0
    }
1907
1908
0
    return(ret);
1909
0
}
1910
1911
typedef struct {
1912
    char *mem;
1913
    const char *cur;
1914
    size_t size;
1915
} xmlMemIOCtxt;
1916
1917
static int
1918
284k
xmlMemRead(void *vctxt, char *buf, int size) {
1919
284k
    xmlMemIOCtxt *ctxt = vctxt;
1920
1921
284k
    if ((size_t) size > ctxt->size)
1922
179k
        size = ctxt->size;
1923
1924
284k
    memcpy(buf, ctxt->cur, size);
1925
284k
    ctxt->cur += size;
1926
284k
    ctxt->size -= size;
1927
1928
284k
    return size;
1929
284k
}
1930
1931
static int
1932
93.7k
xmlMemClose(void *vctxt) {
1933
93.7k
    xmlMemIOCtxt *ctxt = vctxt;
1934
1935
93.7k
    if (ctxt->mem != NULL)
1936
73.2k
        xmlFree(ctxt->mem);
1937
93.7k
    xmlFree(ctxt);
1938
93.7k
    return(0);
1939
93.7k
}
1940
1941
xmlParserInputBufferPtr
1942
xmlNewInputBufferMemory(const void *mem, size_t size, int flags,
1943
93.8k
                        xmlCharEncoding enc) {
1944
93.8k
    xmlParserInputBufferPtr ret;
1945
93.8k
    xmlMemIOCtxt *ctxt;
1946
93.8k
    char *copy = NULL;
1947
1948
93.8k
    if ((flags & XML_INPUT_BUF_STATIC) == 0) {
1949
73.3k
        if (size + 1 == 0)
1950
0
            return(NULL);
1951
73.3k
        copy = xmlMalloc(size + 1);
1952
73.3k
        if (copy == NULL)
1953
17
            return(NULL);
1954
73.3k
        memcpy(copy, mem, size);
1955
73.3k
        copy[size] = 0;
1956
1957
73.3k
        mem = copy;
1958
73.3k
    }
1959
1960
93.8k
    ret = xmlAllocParserInputBuffer(enc);
1961
93.8k
    if (ret == NULL) {
1962
33
        xmlFree(copy);
1963
33
        return(NULL);
1964
33
    }
1965
1966
93.7k
    ctxt = xmlMalloc(sizeof(*ctxt));
1967
93.7k
    if (ctxt == NULL) {
1968
9
        xmlFreeParserInputBuffer(ret);
1969
9
        xmlFree(copy);
1970
9
        return(NULL);
1971
9
    }
1972
1973
93.7k
    ctxt->mem = copy;
1974
93.7k
    ctxt->cur = mem;
1975
93.7k
    ctxt->size = size;
1976
1977
93.7k
    ret->context = ctxt;
1978
93.7k
    ret->readcallback = xmlMemRead;
1979
93.7k
    ret->closecallback = xmlMemClose;
1980
1981
93.7k
    return(ret);
1982
93.7k
}
1983
1984
/**
1985
 * xmlParserInputBufferCreateMem:
1986
 * @mem:  the memory input
1987
 * @size:  the length of the memory block
1988
 * @enc:  the charset encoding if known (deprecated)
1989
 *
1990
 * Create a parser input buffer for parsing from a memory area.
1991
 *
1992
 * This function makes a copy of the whole input buffer. If you are sure
1993
 * that the contents of the buffer will remain valid until the document
1994
 * was parsed, you can avoid the copy by using
1995
 * xmlParserInputBufferCreateStatic.
1996
 *
1997
 * The encoding argument is deprecated and should be set to
1998
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1999
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
2000
 *
2001
 * Returns the new parser input or NULL in case of error.
2002
 */
2003
xmlParserInputBufferPtr
2004
73.3k
xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
2005
73.3k
    if ((mem == NULL) || (size < 0))
2006
0
        return(NULL);
2007
2008
73.3k
    return(xmlNewInputBufferMemory(mem, size, 0, enc));
2009
73.3k
}
2010
2011
/**
2012
 * xmlParserInputBufferCreateStatic:
2013
 * @mem:  the memory input
2014
 * @size:  the length of the memory block
2015
 * @enc:  the charset encoding if known
2016
 *
2017
 * Create a parser input buffer for parsing from a memory area.
2018
 *
2019
 * This functions assumes that the contents of the input buffer remain
2020
 * valid until the document was parsed. Use xmlParserInputBufferCreateMem
2021
 * otherwise.
2022
 *
2023
 * The encoding argument is deprecated and should be set to
2024
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
2025
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
2026
 *
2027
 * Returns the new parser input or NULL in case of error.
2028
 */
2029
xmlParserInputBufferPtr
2030
xmlParserInputBufferCreateStatic(const char *mem, int size,
2031
0
                                 xmlCharEncoding enc) {
2032
0
    if ((mem == NULL) || (size < 0))
2033
0
        return(NULL);
2034
2035
0
    return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
2036
0
}
2037
2038
typedef struct {
2039
    const char *str;
2040
} xmlStringIOCtxt;
2041
2042
static int
2043
45.2k
xmlStringRead(void *vctxt, char *buf, int size) {
2044
45.2k
    xmlStringIOCtxt *ctxt = vctxt;
2045
45.2k
    const char *zero;
2046
45.2k
    size_t len;
2047
2048
45.2k
    zero = memchr(ctxt->str, 0, size);
2049
45.2k
    len = zero ? zero - ctxt->str : size;
2050
2051
45.2k
    memcpy(buf, ctxt->str, len);
2052
45.2k
    ctxt->str += len;
2053
2054
45.2k
    return(len);
2055
45.2k
}
2056
2057
static int
2058
4.64k
xmlStringClose(void *vctxt) {
2059
4.64k
    xmlFree(vctxt);
2060
4.64k
    return(0);
2061
4.64k
}
2062
2063
xmlParserInputBufferPtr
2064
4.65k
xmlNewInputBufferString(const char *str, int flags) {
2065
4.65k
    xmlParserInputBufferPtr ret;
2066
4.65k
    xmlStringIOCtxt *ctxt;
2067
2068
4.65k
    if ((flags & XML_INPUT_BUF_STATIC) == 0)
2069
0
        return(xmlNewInputBufferMemory(str, strlen(str), flags,
2070
0
                                       XML_CHAR_ENCODING_NONE));
2071
2072
4.65k
    ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
2073
4.65k
    if (ret == NULL)
2074
1
        return(NULL);
2075
2076
4.64k
    ctxt = xmlMalloc(sizeof(*ctxt));
2077
4.64k
    if (ctxt == NULL) {
2078
0
        xmlFreeParserInputBuffer(ret);
2079
0
        return(NULL);
2080
0
    }
2081
2082
4.64k
    ctxt->str = str;
2083
2084
4.64k
    ret->context = ctxt;
2085
4.64k
    ret->readcallback = xmlStringRead;
2086
4.64k
    ret->closecallback = xmlStringClose;
2087
2088
4.64k
    return(ret);
2089
4.64k
}
2090
2091
#ifdef LIBXML_OUTPUT_ENABLED
2092
/**
2093
 * xmlOutputBufferCreateFd:
2094
 * @fd:  a file descriptor number
2095
 * @encoder:  the encoding converter or NULL
2096
 *
2097
 * Create a buffered output for the progressive saving
2098
 * to a file descriptor
2099
 *
2100
 * Returns the new parser output or NULL
2101
 */
2102
xmlOutputBufferPtr
2103
0
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
2104
0
    xmlOutputBufferPtr ret;
2105
2106
0
    if (fd < 0) return(NULL);
2107
2108
0
    ret = xmlAllocOutputBufferInternal(encoder);
2109
0
    if (ret != NULL) {
2110
0
        ret->context = (void *) (ptrdiff_t) fd;
2111
0
  ret->writecallback = xmlFdWrite;
2112
0
  ret->closecallback = NULL;
2113
0
    }
2114
2115
0
    return(ret);
2116
0
}
2117
#endif /* LIBXML_OUTPUT_ENABLED */
2118
2119
/**
2120
 * xmlParserInputBufferCreateIO:
2121
 * @ioread:  an I/O read function
2122
 * @ioclose:  an I/O close function
2123
 * @ioctx:  an I/O handler
2124
 * @enc:  the charset encoding if known (deprecated)
2125
 *
2126
 * Create a buffered parser input for the progressive parsing for the input
2127
 * from an I/O handler
2128
 *
2129
 * The encoding argument is deprecated and should be set to
2130
 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
2131
 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
2132
 *
2133
 * Returns the new parser input or NULL
2134
 */
2135
xmlParserInputBufferPtr
2136
xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
2137
0
   xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
2138
0
    xmlParserInputBufferPtr ret;
2139
2140
0
    if (ioread == NULL) return(NULL);
2141
2142
0
    ret = xmlAllocParserInputBuffer(enc);
2143
0
    if (ret != NULL) {
2144
0
        ret->context = (void *) ioctx;
2145
0
  ret->readcallback = ioread;
2146
0
  ret->closecallback = ioclose;
2147
0
    }
2148
2149
0
    return(ret);
2150
0
}
2151
2152
#ifdef LIBXML_OUTPUT_ENABLED
2153
/**
2154
 * xmlOutputBufferCreateIO:
2155
 * @iowrite:  an I/O write function
2156
 * @ioclose:  an I/O close function
2157
 * @ioctx:  an I/O handler
2158
 * @encoder:  the charset encoding if known
2159
 *
2160
 * Create a buffered output for the progressive saving
2161
 * to an I/O handler
2162
 *
2163
 * Returns the new parser output or NULL
2164
 */
2165
xmlOutputBufferPtr
2166
xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
2167
   xmlOutputCloseCallback  ioclose, void *ioctx,
2168
0
   xmlCharEncodingHandlerPtr encoder) {
2169
0
    xmlOutputBufferPtr ret;
2170
2171
0
    if (iowrite == NULL) return(NULL);
2172
2173
0
    ret = xmlAllocOutputBufferInternal(encoder);
2174
0
    if (ret != NULL) {
2175
0
        ret->context = (void *) ioctx;
2176
0
  ret->writecallback = iowrite;
2177
0
  ret->closecallback = ioclose;
2178
0
    }
2179
2180
0
    return(ret);
2181
0
}
2182
#endif /* LIBXML_OUTPUT_ENABLED */
2183
2184
/**
2185
 * xmlParserInputBufferCreateFilenameDefault:
2186
 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
2187
 *
2188
 * Registers a callback for URI input file handling
2189
 *
2190
 * Returns the old value of the registration function
2191
 */
2192
xmlParserInputBufferCreateFilenameFunc
2193
xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
2194
0
{
2195
0
    xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
2196
0
    if (old == NULL) {
2197
0
    old = __xmlParserInputBufferCreateFilename;
2198
0
  }
2199
2200
0
    xmlParserInputBufferCreateFilenameValue = func;
2201
0
    return(old);
2202
0
}
2203
2204
/**
2205
 * xmlOutputBufferCreateFilenameDefault:
2206
 * @func: function pointer to the new OutputBufferCreateFilenameFunc
2207
 *
2208
 * Registers a callback for URI output file handling
2209
 *
2210
 * Returns the old value of the registration function
2211
 */
2212
xmlOutputBufferCreateFilenameFunc
2213
xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
2214
0
{
2215
0
    xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
2216
0
#ifdef LIBXML_OUTPUT_ENABLED
2217
0
    if (old == NULL) {
2218
0
    old = __xmlOutputBufferCreateFilename;
2219
0
  }
2220
0
#endif
2221
0
    xmlOutputBufferCreateFilenameValue = func;
2222
0
    return(old);
2223
0
}
2224
2225
/**
2226
 * xmlParserInputBufferPush:
2227
 * @in:  a buffered parser input
2228
 * @len:  the size in bytes of the array.
2229
 * @buf:  an char array
2230
 *
2231
 * Push the content of the arry in the input buffer
2232
 * This routine handle the I18N transcoding to internal UTF-8
2233
 * This is used when operating the parser in progressive (push) mode.
2234
 *
2235
 * Returns the number of chars read and stored in the buffer, or -1
2236
 *         in case of error.
2237
 */
2238
int
2239
xmlParserInputBufferPush(xmlParserInputBufferPtr in,
2240
0
                   int len, const char *buf) {
2241
0
    int nbchars = 0;
2242
0
    int ret;
2243
2244
0
    if (len < 0) return(0);
2245
0
    if ((in == NULL) || (in->error)) return(-1);
2246
0
    if (in->encoder != NULL) {
2247
        /*
2248
   * Store the data in the incoming raw buffer
2249
   */
2250
0
        if (in->raw == NULL) {
2251
0
      in->raw = xmlBufCreate();
2252
0
            if (in->raw == NULL) {
2253
0
                in->error = XML_ERR_NO_MEMORY;
2254
0
                return(-1);
2255
0
            }
2256
0
  }
2257
0
  ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
2258
0
  if (ret != 0) {
2259
0
            in->error = XML_ERR_NO_MEMORY;
2260
0
      return(-1);
2261
0
        }
2262
2263
  /*
2264
   * convert as much as possible to the parser reading buffer.
2265
   */
2266
0
  nbchars = xmlCharEncInput(in);
2267
0
  if (nbchars < 0)
2268
0
      return(-1);
2269
0
    } else {
2270
0
  nbchars = len;
2271
0
        ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
2272
0
  if (ret != 0) {
2273
0
            in->error = XML_ERR_NO_MEMORY;
2274
0
      return(-1);
2275
0
        }
2276
0
    }
2277
0
    return(nbchars);
2278
0
}
2279
2280
/**
2281
 * endOfInput:
2282
 *
2283
 * When reading from an Input channel indicated end of file or error
2284
 * don't reread from it again.
2285
 */
2286
static int
2287
endOfInput (void * context ATTRIBUTE_UNUSED,
2288
      char * buffer ATTRIBUTE_UNUSED,
2289
8.01M
      int len ATTRIBUTE_UNUSED) {
2290
8.01M
    return(0);
2291
8.01M
}
2292
2293
/**
2294
 * xmlParserInputBufferGrow:
2295
 * @in:  a buffered parser input
2296
 * @len:  indicative value of the amount of chars to read
2297
 *
2298
 * Grow up the content of the input buffer, the old data are preserved
2299
 * This routine handle the I18N transcoding to internal UTF-8
2300
 * This routine is used when operating the parser in normal (pull) mode
2301
 *
2302
 * TODO: one should be able to remove one extra copy by copying directly
2303
 *       onto in->buffer or in->raw
2304
 *
2305
 * Returns the number of chars read and stored in the buffer, or -1
2306
 *         in case of error.
2307
 */
2308
int
2309
8.34M
xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
2310
8.34M
    xmlBufPtr buf;
2311
8.34M
    int res = 0;
2312
2313
8.34M
    if ((in == NULL) || (in->error)) return(-1);
2314
8.34M
    if ((len <= MINLEN) && (len != 4))
2315
8.34M
        len = MINLEN;
2316
2317
8.34M
    if (in->encoder == NULL) {
2318
4.38M
        if (in->readcallback == NULL)
2319
0
            return(0);
2320
4.38M
        buf = in->buffer;
2321
4.38M
    } else {
2322
3.95M
        if (in->raw == NULL) {
2323
2
      in->raw = xmlBufCreate();
2324
2
  }
2325
3.95M
        buf = in->raw;
2326
3.95M
    }
2327
2328
    /*
2329
     * Call the read method for this I/O type.
2330
     */
2331
8.34M
    if (in->readcallback != NULL) {
2332
8.34M
        if (xmlBufGrow(buf, len + 1) < 0) {
2333
3
            in->error = XML_ERR_NO_MEMORY;
2334
3
            return(-1);
2335
3
        }
2336
2337
8.34M
  res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
2338
8.34M
  if (res <= 0)
2339
8.10M
      in->readcallback = endOfInput;
2340
8.34M
        if (res < 0) {
2341
0
            if (res == -1)
2342
0
                in->error = XML_IO_UNKNOWN;
2343
0
            else
2344
0
                in->error = -res;
2345
0
            return(-1);
2346
0
        }
2347
2348
8.34M
        if (xmlBufAddLen(buf, res) < 0) {
2349
0
            in->error = XML_ERR_NO_MEMORY;
2350
0
            return(-1);
2351
0
        }
2352
8.34M
    }
2353
2354
    /*
2355
     * try to establish compressed status of input if not done already
2356
     */
2357
8.34M
    if (in->compressed == -1) {
2358
#ifdef LIBXML_LZMA_ENABLED
2359
  if (in->readcallback == xmlXzfileRead)
2360
            in->compressed = __libxml2_xzcompressed(in->context);
2361
#endif
2362
8.34M
    }
2363
2364
8.34M
    if (in->encoder != NULL) {
2365
3.95M
  res = xmlCharEncInput(in);
2366
3.95M
  if (res < 0)
2367
992
      return(-1);
2368
3.95M
    }
2369
8.34M
    return(res);
2370
8.34M
}
2371
2372
/**
2373
 * xmlParserInputBufferRead:
2374
 * @in:  a buffered parser input
2375
 * @len:  indicative value of the amount of chars to read
2376
 *
2377
 * Refresh the content of the input buffer, the old data are considered
2378
 * consumed
2379
 * This routine handle the I18N transcoding to internal UTF-8
2380
 *
2381
 * Returns the number of chars read and stored in the buffer, or -1
2382
 *         in case of error.
2383
 */
2384
int
2385
0
xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
2386
0
    return(xmlParserInputBufferGrow(in, len));
2387
0
}
2388
2389
#ifdef LIBXML_OUTPUT_ENABLED
2390
/**
2391
 * xmlOutputBufferWrite:
2392
 * @out:  a buffered parser output
2393
 * @len:  the size in bytes of the array.
2394
 * @buf:  an char array
2395
 *
2396
 * Write the content of the array in the output I/O buffer
2397
 * This routine handle the I18N transcoding from internal UTF-8
2398
 * The buffer is lossless, i.e. will store in case of partial
2399
 * or delayed writes.
2400
 *
2401
 * Returns the number of chars immediately written, or -1
2402
 *         in case of error.
2403
 */
2404
int
2405
9.06M
xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
2406
9.06M
    int nbchars = 0; /* number of chars to output to I/O */
2407
9.06M
    int ret;         /* return from function call */
2408
9.06M
    int written = 0; /* number of char written to I/O so far */
2409
9.06M
    int chunk;       /* number of byte current processed from buf */
2410
2411
9.06M
    if ((out == NULL) || (out->error)) return(-1);
2412
9.05M
    if (len < 0) return(0);
2413
9.05M
    if (out->error) return(-1);
2414
2415
9.05M
    do {
2416
9.05M
  chunk = len;
2417
9.05M
  if (chunk > 4 * MINLEN)
2418
1.23k
      chunk = 4 * MINLEN;
2419
2420
  /*
2421
   * first handle encoding stuff.
2422
   */
2423
9.05M
  if (out->encoder != NULL) {
2424
      /*
2425
       * Store the data in the incoming raw buffer
2426
       */
2427
504k
      if (out->conv == NULL) {
2428
0
    out->conv = xmlBufCreate();
2429
0
                if (out->conv == NULL) {
2430
0
                    out->error = XML_ERR_NO_MEMORY;
2431
0
                    return(-1);
2432
0
                }
2433
0
      }
2434
504k
      ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
2435
504k
      if (ret != 0) {
2436
0
                out->error = XML_ERR_NO_MEMORY;
2437
0
          return(-1);
2438
0
            }
2439
2440
504k
      if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len))
2441
504k
    goto done;
2442
2443
      /*
2444
       * convert as much as possible to the parser reading buffer.
2445
       */
2446
654
      ret = xmlCharEncOutput(out, 0);
2447
654
      if (ret < 0)
2448
3
    return(-1);
2449
651
            if (out->writecallback)
2450
0
          nbchars = xmlBufUse(out->conv);
2451
651
            else
2452
651
                nbchars = ret >= 0 ? ret : 0;
2453
8.54M
  } else {
2454
8.54M
      ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
2455
8.54M
      if (ret != 0)
2456
4.55k
          return(-1);
2457
8.54M
            if (out->writecallback)
2458
0
          nbchars = xmlBufUse(out->buffer);
2459
8.54M
            else
2460
8.54M
                nbchars = chunk;
2461
8.54M
  }
2462
8.54M
  buf += chunk;
2463
8.54M
  len -= chunk;
2464
2465
8.54M
  if (out->writecallback) {
2466
0
            if ((nbchars < MINLEN) && (len <= 0))
2467
0
                goto done;
2468
2469
      /*
2470
       * second write the stuff to the I/O channel
2471
       */
2472
0
      if (out->encoder != NULL) {
2473
0
    ret = out->writecallback(out->context,
2474
0
                           (const char *)xmlBufContent(out->conv), nbchars);
2475
0
    if (ret >= 0)
2476
0
        xmlBufShrink(out->conv, ret);
2477
0
      } else {
2478
0
    ret = out->writecallback(out->context,
2479
0
                           (const char *)xmlBufContent(out->buffer), nbchars);
2480
0
    if (ret >= 0)
2481
0
        xmlBufShrink(out->buffer, ret);
2482
0
      }
2483
0
      if (ret < 0) {
2484
0
                int errNo = (ret == -1) ? XML_IO_WRITE : -ret;
2485
2486
0
    xmlIOErr(errNo, NULL);
2487
0
    out->error = errNo;
2488
0
    return(ret);
2489
0
      }
2490
0
            if (out->written > INT_MAX - ret)
2491
0
                out->written = INT_MAX;
2492
0
            else
2493
0
                out->written += ret;
2494
0
  }
2495
8.54M
  written += nbchars;
2496
8.54M
    } while (len > 0);
2497
2498
9.04M
done:
2499
9.04M
    return(written);
2500
9.05M
}
2501
2502
/**
2503
 * xmlEscapeContent:
2504
 * @out:  a pointer to an array of bytes to store the result
2505
 * @outlen:  the length of @out
2506
 * @in:  a pointer to an array of unescaped UTF-8 bytes
2507
 * @inlen:  the length of @in
2508
 *
2509
 * Take a block of UTF-8 chars in and escape them.
2510
 * Returns 0 if success, or -1 otherwise
2511
 * The value of @inlen after return is the number of octets consumed
2512
 *     if the return value is positive, else unpredictable.
2513
 * The value of @outlen after return is the number of octets consumed.
2514
 */
2515
static int
2516
xmlEscapeContent(unsigned char* out, int *outlen,
2517
122k
                 const xmlChar* in, int *inlen) {
2518
122k
    unsigned char* outstart = out;
2519
122k
    const unsigned char* base = in;
2520
122k
    unsigned char* outend = out + *outlen;
2521
122k
    const unsigned char* inend;
2522
2523
122k
    inend = in + (*inlen);
2524
2525
660M
    while ((in < inend) && (out < outend)) {
2526
660M
  if (*in == '<') {
2527
4.11M
      if (outend - out < 4) break;
2528
4.11M
      *out++ = '&';
2529
4.11M
      *out++ = 'l';
2530
4.11M
      *out++ = 't';
2531
4.11M
      *out++ = ';';
2532
655M
  } else if (*in == '>') {
2533
4.74M
      if (outend - out < 4) break;
2534
4.74M
      *out++ = '&';
2535
4.74M
      *out++ = 'g';
2536
4.74M
      *out++ = 't';
2537
4.74M
      *out++ = ';';
2538
651M
  } else if (*in == '&') {
2539
21.5M
      if (outend - out < 5) break;
2540
21.5M
      *out++ = '&';
2541
21.5M
      *out++ = 'a';
2542
21.5M
      *out++ = 'm';
2543
21.5M
      *out++ = 'p';
2544
21.5M
      *out++ = ';';
2545
629M
  } else if (*in == '\r') {
2546
1.10k
      if (outend - out < 5) break;
2547
1.09k
      *out++ = '&';
2548
1.09k
      *out++ = '#';
2549
1.09k
      *out++ = '1';
2550
1.09k
      *out++ = '3';
2551
1.09k
      *out++ = ';';
2552
629M
  } else {
2553
629M
      *out++ = *in;
2554
629M
  }
2555
660M
  ++in;
2556
660M
    }
2557
122k
    *outlen = out - outstart;
2558
122k
    *inlen = in - base;
2559
122k
    return(0);
2560
122k
}
2561
2562
/**
2563
 * xmlOutputBufferWriteEscape:
2564
 * @out:  a buffered parser output
2565
 * @str:  a zero terminated UTF-8 string
2566
 * @escaping:  an optional escaping function (or NULL)
2567
 *
2568
 * Write the content of the string in the output I/O buffer
2569
 * This routine escapes the characters and then handle the I18N
2570
 * transcoding from internal UTF-8
2571
 * The buffer is lossless, i.e. will store in case of partial
2572
 * or delayed writes.
2573
 *
2574
 * Returns the number of chars immediately written, or -1
2575
 *         in case of error.
2576
 */
2577
int
2578
xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
2579
100k
                           xmlCharEncodingOutputFunc escaping) {
2580
100k
    int nbchars = 0; /* number of chars to output to I/O */
2581
100k
    int ret;         /* return from function call */
2582
100k
    int written = 0; /* number of char written to I/O so far */
2583
100k
    int oldwritten=0;/* loop guard */
2584
100k
    int chunk;       /* number of byte currently processed from str */
2585
100k
    int len;         /* number of bytes in str */
2586
100k
    int cons;        /* byte from str consumed */
2587
2588
100k
    if ((out == NULL) || (out->error) || (str == NULL) ||
2589
100k
        (out->buffer == NULL))
2590
475
        return(-1);
2591
100k
    len = strlen((const char *)str);
2592
100k
    if (len < 0) return(0);
2593
100k
    if (out->error) return(-1);
2594
100k
    if (escaping == NULL) escaping = xmlEscapeContent;
2595
2596
122k
    do {
2597
122k
        oldwritten = written;
2598
2599
        /*
2600
   * how many bytes to consume and how many bytes to store.
2601
   */
2602
122k
  cons = len;
2603
122k
  chunk = xmlBufAvail(out->buffer);
2604
2605
        /*
2606
   * make sure we have enough room to save first, if this is
2607
   * not the case force a flush, but make sure we stay in the loop
2608
   */
2609
122k
  if (chunk < 40) {
2610
219
      if (xmlBufGrow(out->buffer, 100) < 0)
2611
219
          return(-1);
2612
0
            oldwritten = -1;
2613
0
      continue;
2614
219
  }
2615
2616
  /*
2617
   * first handle encoding stuff.
2618
   */
2619
122k
  if (out->encoder != NULL) {
2620
      /*
2621
       * Store the data in the incoming raw buffer
2622
       */
2623
28.9k
      if (out->conv == NULL) {
2624
0
    out->conv = xmlBufCreate();
2625
0
      }
2626
28.9k
      ret = escaping(xmlBufEnd(out->buffer) ,
2627
28.9k
                     &chunk, str, &cons);
2628
28.9k
      if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
2629
0
          return(-1);
2630
28.9k
            xmlBufAddLen(out->buffer, chunk);
2631
2632
28.9k
      if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
2633
6.47k
    goto done;
2634
2635
      /*
2636
       * convert as much as possible to the output buffer.
2637
       */
2638
22.5k
      ret = xmlCharEncOutput(out, 0);
2639
22.5k
      if (ret < 0)
2640
2
    return(-1);
2641
22.5k
            if (out->writecallback)
2642
0
          nbchars = xmlBufUse(out->conv);
2643
22.5k
            else
2644
22.5k
                nbchars = ret >= 0 ? ret : 0;
2645
93.7k
  } else {
2646
93.7k
      ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
2647
93.7k
      if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
2648
866
          return(-1);
2649
92.8k
            xmlBufAddLen(out->buffer, chunk);
2650
92.8k
            if (out->writecallback)
2651
0
          nbchars = xmlBufUse(out->buffer);
2652
92.8k
            else
2653
92.8k
                nbchars = chunk;
2654
92.8k
  }
2655
115k
  str += cons;
2656
115k
  len -= cons;
2657
2658
115k
  if (out->writecallback) {
2659
0
            if ((nbchars < MINLEN) && (len <= 0))
2660
0
                goto done;
2661
2662
      /*
2663
       * second write the stuff to the I/O channel
2664
       */
2665
0
      if (out->encoder != NULL) {
2666
0
    ret = out->writecallback(out->context,
2667
0
                           (const char *)xmlBufContent(out->conv), nbchars);
2668
0
    if (ret >= 0)
2669
0
        xmlBufShrink(out->conv, ret);
2670
0
      } else {
2671
0
    ret = out->writecallback(out->context,
2672
0
                           (const char *)xmlBufContent(out->buffer), nbchars);
2673
0
    if (ret >= 0)
2674
0
        xmlBufShrink(out->buffer, ret);
2675
0
      }
2676
0
      if (ret < 0) {
2677
0
                int errNo = (ret == -1) ? XML_IO_WRITE : -ret;
2678
0
    xmlIOErr(errNo, NULL);
2679
0
    out->error = errNo;
2680
0
    return(ret);
2681
0
      }
2682
0
            if (out->written > INT_MAX - ret)
2683
0
                out->written = INT_MAX;
2684
0
            else
2685
0
                out->written += ret;
2686
115k
  } else if (xmlBufAvail(out->buffer) < MINLEN) {
2687
1.20k
      xmlBufGrow(out->buffer, MINLEN);
2688
1.20k
  }
2689
115k
  written += nbchars;
2690
115k
    } while ((len > 0) && (oldwritten != written));
2691
2692
99.3k
done:
2693
99.3k
    return(written);
2694
100k
}
2695
2696
/**
2697
 * xmlOutputBufferWriteString:
2698
 * @out:  a buffered parser output
2699
 * @str:  a zero terminated C string
2700
 *
2701
 * Write the content of the string in the output I/O buffer
2702
 * This routine handle the I18N transcoding from internal UTF-8
2703
 * The buffer is lossless, i.e. will store in case of partial
2704
 * or delayed writes.
2705
 *
2706
 * Returns the number of chars immediately written, or -1
2707
 *         in case of error.
2708
 */
2709
int
2710
7.68M
xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
2711
7.68M
    int len;
2712
2713
7.68M
    if ((out == NULL) || (out->error)) return(-1);
2714
7.67M
    if (str == NULL)
2715
0
        return(-1);
2716
7.67M
    len = strlen(str);
2717
2718
7.67M
    if (len > 0)
2719
7.65M
  return(xmlOutputBufferWrite(out, len, str));
2720
23.5k
    return(len);
2721
7.67M
}
2722
2723
/**
2724
 * xmlOutputBufferWriteQuotedString:
2725
 * @buf:  output buffer
2726
 * @string:  the string to add
2727
 *
2728
 * routine which manage and grows an output buffer. This one writes
2729
 * a quoted or double quoted #xmlChar string, checking first if it holds
2730
 * quote or double-quotes internally
2731
 */
2732
void
2733
xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,
2734
162k
                                 const xmlChar *string) {
2735
162k
    const xmlChar *cur, *base;
2736
2737
162k
    if ((buf == NULL) || (buf->error))
2738
4.35k
        return;
2739
2740
158k
    if (xmlStrchr(string, '\"')) {
2741
1.03k
        if (xmlStrchr(string, '\'')) {
2742
605
      xmlOutputBufferWrite(buf, 1, "\"");
2743
605
            base = cur = string;
2744
19.4M
            while(*cur != 0){
2745
19.4M
                if(*cur == '"'){
2746
8.67k
                    if (base != cur)
2747
8.33k
                        xmlOutputBufferWrite(buf, cur - base,
2748
8.33k
                                             (const char *) base);
2749
8.67k
                    xmlOutputBufferWrite(buf, 6, "&quot;");
2750
8.67k
                    cur++;
2751
8.67k
                    base = cur;
2752
8.67k
                }
2753
19.4M
                else {
2754
19.4M
                    cur++;
2755
19.4M
                }
2756
19.4M
            }
2757
605
            if (base != cur)
2758
601
                xmlOutputBufferWrite(buf, cur - base, (const char *) base);
2759
605
      xmlOutputBufferWrite(buf, 1, "\"");
2760
605
  }
2761
427
        else{
2762
427
      xmlOutputBufferWrite(buf, 1, "'");
2763
427
            xmlOutputBufferWriteString(buf, (const char *) string);
2764
427
      xmlOutputBufferWrite(buf, 1, "'");
2765
427
        }
2766
157k
    } else {
2767
157k
        xmlOutputBufferWrite(buf, 1, "\"");
2768
157k
        xmlOutputBufferWriteString(buf, (const char *) string);
2769
157k
        xmlOutputBufferWrite(buf, 1, "\"");
2770
157k
    }
2771
158k
}
2772
2773
/**
2774
 * xmlOutputBufferFlush:
2775
 * @out:  a buffered output
2776
 *
2777
 * flushes the output I/O channel
2778
 *
2779
 * Returns the number of byte written or -1 in case of error.
2780
 */
2781
int
2782
1.95k
xmlOutputBufferFlush(xmlOutputBufferPtr out) {
2783
1.95k
    int nbchars = 0, ret = 0;
2784
2785
1.95k
    if ((out == NULL) || (out->error)) return(-1);
2786
    /*
2787
     * first handle encoding stuff.
2788
     */
2789
1.93k
    if ((out->conv != NULL) && (out->encoder != NULL)) {
2790
  /*
2791
   * convert as much as possible to the parser output buffer.
2792
   */
2793
205
  do {
2794
205
      nbchars = xmlCharEncOutput(out, 0);
2795
205
      if (nbchars < 0)
2796
0
    return(-1);
2797
205
  } while (nbchars);
2798
103
    }
2799
2800
    /*
2801
     * second flush the stuff to the I/O channel
2802
     */
2803
1.93k
    if ((out->conv != NULL) && (out->encoder != NULL) &&
2804
1.93k
  (out->writecallback != NULL)) {
2805
0
  ret = out->writecallback(out->context,
2806
0
                                 (const char *)xmlBufContent(out->conv),
2807
0
                                 xmlBufUse(out->conv));
2808
0
  if (ret >= 0)
2809
0
      xmlBufShrink(out->conv, ret);
2810
1.93k
    } else if (out->writecallback != NULL) {
2811
0
  ret = out->writecallback(out->context,
2812
0
                                 (const char *)xmlBufContent(out->buffer),
2813
0
                                 xmlBufUse(out->buffer));
2814
0
  if (ret >= 0)
2815
0
      xmlBufShrink(out->buffer, ret);
2816
0
    }
2817
1.93k
    if (ret < 0) {
2818
0
        int errNo = (ret == -1) ? XML_IO_WRITE : -ret;
2819
2820
0
        xmlIOErr(errNo, NULL);
2821
0
        out->error = errNo;
2822
0
  return(ret);
2823
0
    }
2824
1.93k
    if (out->written > INT_MAX - ret)
2825
0
        out->written = INT_MAX;
2826
1.93k
    else
2827
1.93k
        out->written += ret;
2828
2829
1.93k
    return(ret);
2830
1.93k
}
2831
#endif /* LIBXML_OUTPUT_ENABLED */
2832
2833
/**
2834
 * xmlParserGetDirectory:
2835
 * @filename:  the path to a file
2836
 *
2837
 * lookup the directory for that file
2838
 *
2839
 * Returns a new allocated string containing the directory, or NULL.
2840
 */
2841
char *
2842
0
xmlParserGetDirectory(const char *filename) {
2843
0
    char *ret = NULL;
2844
0
    char dir[1024];
2845
0
    char *cur;
2846
2847
0
    if (filename == NULL) return(NULL);
2848
2849
#if defined(_WIN32)
2850
#   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
2851
#else
2852
0
#   define IS_XMLPGD_SEP(ch) (ch=='/')
2853
0
#endif
2854
2855
0
    strncpy(dir, filename, 1023);
2856
0
    dir[1023] = 0;
2857
0
    cur = &dir[strlen(dir)];
2858
0
    while (cur > dir) {
2859
0
         if (IS_XMLPGD_SEP(*cur)) break;
2860
0
   cur --;
2861
0
    }
2862
0
    if (IS_XMLPGD_SEP(*cur)) {
2863
0
        if (cur == dir) dir[1] = 0;
2864
0
  else *cur = 0;
2865
0
  ret = xmlMemStrdup(dir);
2866
0
    } else {
2867
0
        if (getcwd(dir, 1024) != NULL) {
2868
0
      dir[1023] = 0;
2869
0
      ret = xmlMemStrdup(dir);
2870
0
  }
2871
0
    }
2872
0
    return(ret);
2873
0
#undef IS_XMLPGD_SEP
2874
0
}
2875
2876
/**
2877
 * xmlNoNetExists:
2878
 * @filename:  the path to check
2879
 *
2880
 * DEPRECATED: Internal function, don't use.
2881
 *
2882
 * Like xmlCheckFilename but handles file URIs.
2883
 */
2884
int
2885
0
xmlNoNetExists(const char *filename) {
2886
0
    char *fromUri;
2887
0
    int ret;
2888
2889
0
    if (filename == NULL)
2890
0
  return(0);
2891
2892
0
    if (xmlConvertUriToPath(filename, &fromUri) < 0)
2893
0
        return(0);
2894
2895
0
    if (fromUri != NULL)
2896
0
        filename = fromUri;
2897
2898
0
    ret =  xmlCheckFilename(filename);
2899
2900
0
    xmlFree(fromUri);
2901
0
    return(ret);
2902
0
}
2903
2904
/************************************************************************
2905
 *                  *
2906
 *      Input/output callbacks        *
2907
 *                  *
2908
 ************************************************************************/
2909
2910
/**
2911
 * xmlInitIOCallbacks:
2912
 *
2913
 * Initialize callback tables.
2914
 */
2915
void
2916
xmlInitIOCallbacks(void)
2917
4
{
2918
4
    xmlInputCallbackNr = 1;
2919
4
    xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2920
2921
4
#ifdef LIBXML_OUTPUT_ENABLED
2922
4
    xmlOutputCallbackNr = 1;
2923
4
    xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2924
4
#endif
2925
4
}
2926
2927
/**
2928
 * xmlRegisterInputCallbacks:
2929
 * @matchFunc:  the xmlInputMatchCallback
2930
 * @openFunc:  the xmlInputOpenCallback
2931
 * @readFunc:  the xmlInputReadCallback
2932
 * @closeFunc:  the xmlInputCloseCallback
2933
 *
2934
 * Register a new set of I/O callback for handling parser input.
2935
 *
2936
 * Returns the registered handler number or -1 in case of error
2937
 */
2938
int
2939
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2940
  xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2941
0
  xmlInputCloseCallback closeFunc) {
2942
0
    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2943
0
  return(-1);
2944
0
    }
2945
0
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2946
0
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2947
0
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2948
0
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2949
0
    return(xmlInputCallbackNr++);
2950
0
}
2951
2952
/**
2953
 * xmlRegisterDefaultInputCallbacks:
2954
 *
2955
 * Registers the default compiled-in I/O handlers.
2956
 */
2957
void
2958
0
xmlRegisterDefaultInputCallbacks(void) {
2959
0
    xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2960
0
}
2961
2962
/**
2963
 * xmlPopInputCallbacks:
2964
 *
2965
 * Clear the top input callback from the input stack. this includes the
2966
 * compiled-in I/O.
2967
 *
2968
 * Returns the number of input callback registered or -1 in case of error.
2969
 */
2970
int
2971
xmlPopInputCallbacks(void)
2972
0
{
2973
0
    if (xmlInputCallbackNr <= 0)
2974
0
        return(-1);
2975
2976
0
    xmlInputCallbackNr--;
2977
2978
0
    return(xmlInputCallbackNr);
2979
0
}
2980
2981
/**
2982
 * xmlCleanupInputCallbacks:
2983
 *
2984
 * clears the entire input callback table. this includes the
2985
 * compiled-in I/O.
2986
 */
2987
void
2988
xmlCleanupInputCallbacks(void)
2989
0
{
2990
0
    xmlInputCallbackNr = 0;
2991
0
}
2992
2993
#ifdef LIBXML_OUTPUT_ENABLED
2994
/**
2995
 * xmlRegisterOutputCallbacks:
2996
 * @matchFunc:  the xmlOutputMatchCallback
2997
 * @openFunc:  the xmlOutputOpenCallback
2998
 * @writeFunc:  the xmlOutputWriteCallback
2999
 * @closeFunc:  the xmlOutputCloseCallback
3000
 *
3001
 * Register a new set of I/O callback for handling output.
3002
 *
3003
 * Returns the registered handler number or -1 in case of error
3004
 */
3005
int
3006
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
3007
  xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
3008
0
  xmlOutputCloseCallback closeFunc) {
3009
0
    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
3010
0
  return(-1);
3011
0
    }
3012
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
3013
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
3014
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
3015
0
    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
3016
0
    return(xmlOutputCallbackNr++);
3017
0
}
3018
3019
/**
3020
 * xmlRegisterDefaultOutputCallbacks:
3021
 *
3022
 * Registers the default compiled-in I/O handlers.
3023
 */
3024
void
3025
0
xmlRegisterDefaultOutputCallbacks (void) {
3026
0
    xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
3027
0
}
3028
3029
/**
3030
 * xmlPopOutputCallbacks:
3031
 *
3032
 * Remove the top output callbacks from the output stack. This includes the
3033
 * compiled-in I/O.
3034
 *
3035
 * Returns the number of output callback registered or -1 in case of error.
3036
 */
3037
int
3038
xmlPopOutputCallbacks(void)
3039
0
{
3040
0
    if (xmlOutputCallbackNr <= 0)
3041
0
        return(-1);
3042
3043
0
    xmlOutputCallbackNr--;
3044
3045
0
    return(xmlOutputCallbackNr);
3046
0
}
3047
3048
/**
3049
 * xmlCleanupOutputCallbacks:
3050
 *
3051
 * clears the entire output callback table. this includes the
3052
 * compiled-in I/O callbacks.
3053
 */
3054
void
3055
xmlCleanupOutputCallbacks(void)
3056
0
{
3057
0
    xmlOutputCallbackNr = 0;
3058
0
}
3059
3060
#ifdef LIBXML_HTTP_ENABLED
3061
/**
3062
 * xmlRegisterHTTPPostCallbacks:
3063
 *
3064
 * DEPRECATED: Support for HTTP POST has been removed.
3065
 */
3066
void
3067
0
xmlRegisterHTTPPostCallbacks(void) {
3068
0
    xmlRegisterDefaultOutputCallbacks();
3069
0
}
3070
#endif
3071
#endif /* LIBXML_OUTPUT_ENABLED */
3072