VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/xmlIO.c@ 105420

最後變更 在這個檔案從105420是 105420,由 vboxsync 提交於 4 月 前

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette