VirtualBox

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

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

libxml2-2.13.2: builds and runs on Linux. bugref:10730

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

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