2 * xmlIO.c : implementation of the I/O interfaces used by the parser
4 * See Copyright for the status of this software.
8 * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
18 #ifdef HAVE_SYS_TYPES_H
19 #include <sys/types.h>
21 #ifdef HAVE_SYS_STAT_H
30 #ifdef LIBXML_ZLIB_ENABLED
33 #ifdef LIBXML_LZMA_ENABLED
38 #define WIN32_LEAN_AND_MEAN
46 # define S_ISDIR(x) _S_ISDIR(x)
47 # elif defined(S_IFDIR)
49 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
50 # elif defined(_S_IFMT)
51 # define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
56 #include <libxml/xmlmemory.h>
57 #include <libxml/parser.h>
58 #include <libxml/parserInternals.h>
59 #include <libxml/xmlIO.h>
60 #include <libxml/uri.h>
61 #include <libxml/nanohttp.h>
62 #include <libxml/nanoftp.h>
63 #include <libxml/xmlerror.h>
64 #ifdef LIBXML_CATALOG_ENABLED
65 #include <libxml/catalog.h>
67 #include <libxml/globals.h>
72 /* #define VERBOSE_FAILURE */
73 /* #define DEBUG_EXTERNAL_ENTITIES */
74 /* #define DEBUG_INPUT */
83 * Input I/O callback sets
85 typedef struct _xmlInputCallback
{
86 xmlInputMatchCallback matchcallback
;
87 xmlInputOpenCallback opencallback
;
88 xmlInputReadCallback readcallback
;
89 xmlInputCloseCallback closecallback
;
92 #define MAX_INPUT_CALLBACK 15
94 static xmlInputCallback xmlInputCallbackTable
[MAX_INPUT_CALLBACK
];
95 static int xmlInputCallbackNr
= 0;
96 static int xmlInputCallbackInitialized
= 0;
98 #ifdef LIBXML_OUTPUT_ENABLED
100 * Output I/O callback sets
102 typedef struct _xmlOutputCallback
{
103 xmlOutputMatchCallback matchcallback
;
104 xmlOutputOpenCallback opencallback
;
105 xmlOutputWriteCallback writecallback
;
106 xmlOutputCloseCallback closecallback
;
109 #define MAX_OUTPUT_CALLBACK 15
111 static xmlOutputCallback xmlOutputCallbackTable
[MAX_OUTPUT_CALLBACK
];
112 static int xmlOutputCallbackNr
= 0;
113 static int xmlOutputCallbackInitialized
= 0;
116 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder
);
117 #endif /* LIBXML_OUTPUT_ENABLED */
119 /************************************************************************
121 * Tree memory error handler *
123 ************************************************************************/
125 static const char* const IOerr
[] = {
126 "Unknown IO error", /* UNKNOWN */
127 "Permission denied", /* EACCES */
128 "Resource temporarily unavailable",/* EAGAIN */
129 "Bad file descriptor", /* EBADF */
130 "Bad message", /* EBADMSG */
131 "Resource busy", /* EBUSY */
132 "Operation canceled", /* ECANCELED */
133 "No child processes", /* ECHILD */
134 "Resource deadlock avoided",/* EDEADLK */
135 "Domain error", /* EDOM */
136 "File exists", /* EEXIST */
137 "Bad address", /* EFAULT */
138 "File too large", /* EFBIG */
139 "Operation in progress", /* EINPROGRESS */
140 "Interrupted function call",/* EINTR */
141 "Invalid argument", /* EINVAL */
142 "Input/output error", /* EIO */
143 "Is a directory", /* EISDIR */
144 "Too many open files", /* EMFILE */
145 "Too many links", /* EMLINK */
146 "Inappropriate message buffer length",/* EMSGSIZE */
147 "Filename too long", /* ENAMETOOLONG */
148 "Too many open files in system",/* ENFILE */
149 "No such device", /* ENODEV */
150 "No such file or directory",/* ENOENT */
151 "Exec format error", /* ENOEXEC */
152 "No locks available", /* ENOLCK */
153 "Not enough space", /* ENOMEM */
154 "No space left on device", /* ENOSPC */
155 "Function not implemented", /* ENOSYS */
156 "Not a directory", /* ENOTDIR */
157 "Directory not empty", /* ENOTEMPTY */
158 "Not supported", /* ENOTSUP */
159 "Inappropriate I/O control operation",/* ENOTTY */
160 "No such device or address",/* ENXIO */
161 "Operation not permitted", /* EPERM */
162 "Broken pipe", /* EPIPE */
163 "Result too large", /* ERANGE */
164 "Read-only file system", /* EROFS */
165 "Invalid seek", /* ESPIPE */
166 "No such process", /* ESRCH */
167 "Operation timed out", /* ETIMEDOUT */
168 "Improper link", /* EXDEV */
169 "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
170 "encoder error", /* XML_IO_ENCODER */
176 "not a socket", /* ENOTSOCK */
177 "already connected", /* EISCONN */
178 "connection refused", /* ECONNREFUSED */
179 "unreachable network", /* ENETUNREACH */
180 "address in use", /* EADDRINUSE */
181 "already in use", /* EALREADY */
182 "unknown address family", /* EAFNOSUPPORT */
187 * __xmlIOWin32UTF8ToWChar:
188 * @u8String: uft-8 string
190 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
193 __xmlIOWin32UTF8ToWChar(const char *u8String
)
195 wchar_t *wString
= NULL
;
199 MultiByteToWideChar(CP_UTF8
, MB_ERR_INVALID_CHARS
, u8String
,
202 wString
= xmlMalloc(wLen
* sizeof(wchar_t));
204 if (MultiByteToWideChar
205 (CP_UTF8
, 0, u8String
, -1, wString
, wLen
) == 0) {
219 * @extra: extra information
221 * Handle an out of memory condition
224 xmlIOErrMemory(const char *extra
)
226 __xmlSimpleError(XML_FROM_IO
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
231 * @code: the error number
233 * @extra: extra information
235 * Handle an I/O error
238 __xmlIOErr(int domain
, int code
, const char *extra
)
243 if (errno
== 0) code
= 0;
245 else if (errno
== EACCES
) code
= XML_IO_EACCES
;
248 else if (errno
== EAGAIN
) code
= XML_IO_EAGAIN
;
251 else if (errno
== EBADF
) code
= XML_IO_EBADF
;
254 else if (errno
== EBADMSG
) code
= XML_IO_EBADMSG
;
257 else if (errno
== EBUSY
) code
= XML_IO_EBUSY
;
260 else if (errno
== ECANCELED
) code
= XML_IO_ECANCELED
;
263 else if (errno
== ECHILD
) code
= XML_IO_ECHILD
;
266 else if (errno
== EDEADLK
) code
= XML_IO_EDEADLK
;
269 else if (errno
== EDOM
) code
= XML_IO_EDOM
;
272 else if (errno
== EEXIST
) code
= XML_IO_EEXIST
;
275 else if (errno
== EFAULT
) code
= XML_IO_EFAULT
;
278 else if (errno
== EFBIG
) code
= XML_IO_EFBIG
;
281 else if (errno
== EINPROGRESS
) code
= XML_IO_EINPROGRESS
;
284 else if (errno
== EINTR
) code
= XML_IO_EINTR
;
287 else if (errno
== EINVAL
) code
= XML_IO_EINVAL
;
290 else if (errno
== EIO
) code
= XML_IO_EIO
;
293 else if (errno
== EISDIR
) code
= XML_IO_EISDIR
;
296 else if (errno
== EMFILE
) code
= XML_IO_EMFILE
;
299 else if (errno
== EMLINK
) code
= XML_IO_EMLINK
;
302 else if (errno
== EMSGSIZE
) code
= XML_IO_EMSGSIZE
;
305 else if (errno
== ENAMETOOLONG
) code
= XML_IO_ENAMETOOLONG
;
308 else if (errno
== ENFILE
) code
= XML_IO_ENFILE
;
311 else if (errno
== ENODEV
) code
= XML_IO_ENODEV
;
314 else if (errno
== ENOENT
) code
= XML_IO_ENOENT
;
317 else if (errno
== ENOEXEC
) code
= XML_IO_ENOEXEC
;
320 else if (errno
== ENOLCK
) code
= XML_IO_ENOLCK
;
323 else if (errno
== ENOMEM
) code
= XML_IO_ENOMEM
;
326 else if (errno
== ENOSPC
) code
= XML_IO_ENOSPC
;
329 else if (errno
== ENOSYS
) code
= XML_IO_ENOSYS
;
332 else if (errno
== ENOTDIR
) code
= XML_IO_ENOTDIR
;
335 else if (errno
== ENOTEMPTY
) code
= XML_IO_ENOTEMPTY
;
338 else if (errno
== ENOTSUP
) code
= XML_IO_ENOTSUP
;
341 else if (errno
== ENOTTY
) code
= XML_IO_ENOTTY
;
344 else if (errno
== ENXIO
) code
= XML_IO_ENXIO
;
347 else if (errno
== EPERM
) code
= XML_IO_EPERM
;
350 else if (errno
== EPIPE
) code
= XML_IO_EPIPE
;
353 else if (errno
== ERANGE
) code
= XML_IO_ERANGE
;
356 else if (errno
== EROFS
) code
= XML_IO_EROFS
;
359 else if (errno
== ESPIPE
) code
= XML_IO_ESPIPE
;
362 else if (errno
== ESRCH
) code
= XML_IO_ESRCH
;
365 else if (errno
== ETIMEDOUT
) code
= XML_IO_ETIMEDOUT
;
368 else if (errno
== EXDEV
) code
= XML_IO_EXDEV
;
371 else if (errno
== ENOTSOCK
) code
= XML_IO_ENOTSOCK
;
374 else if (errno
== EISCONN
) code
= XML_IO_EISCONN
;
377 else if (errno
== ECONNREFUSED
) code
= XML_IO_ECONNREFUSED
;
380 else if (errno
== ETIMEDOUT
) code
= XML_IO_ETIMEDOUT
;
383 else if (errno
== ENETUNREACH
) code
= XML_IO_ENETUNREACH
;
386 else if (errno
== EADDRINUSE
) code
= XML_IO_EADDRINUSE
;
389 else if (errno
== EINPROGRESS
) code
= XML_IO_EINPROGRESS
;
392 else if (errno
== EALREADY
) code
= XML_IO_EALREADY
;
395 else if (errno
== EAFNOSUPPORT
) code
= XML_IO_EAFNOSUPPORT
;
397 else code
= XML_IO_UNKNOWN
;
400 if (code
>= XML_IO_UNKNOWN
) idx
= code
- XML_IO_UNKNOWN
;
401 if (idx
>= (sizeof(IOerr
) / sizeof(IOerr
[0]))) idx
= 0;
403 __xmlSimpleError(domain
, code
, NULL
, IOerr
[idx
], extra
);
408 * @code: the error number
409 * @extra: extra information
411 * Handle an I/O error
414 xmlIOErr(int code
, const char *extra
)
416 __xmlIOErr(XML_FROM_IO
, code
, extra
);
421 * @ctx: the parser context
422 * @extra: extra information
424 * Handle a resource access error
427 __xmlLoaderErr(void *ctx
, const char *msg
, const char *filename
)
429 xmlParserCtxtPtr ctxt
= (xmlParserCtxtPtr
) ctx
;
430 xmlStructuredErrorFunc schannel
= NULL
;
431 xmlGenericErrorFunc channel
= NULL
;
433 xmlErrorLevel level
= XML_ERR_ERROR
;
435 if ((ctxt
!= NULL
) && (ctxt
->disableSAX
!= 0) &&
436 (ctxt
->instate
== XML_PARSER_EOF
))
438 if ((ctxt
!= NULL
) && (ctxt
->sax
!= NULL
)) {
439 if (ctxt
->validate
) {
440 channel
= ctxt
->sax
->error
;
441 level
= XML_ERR_ERROR
;
443 channel
= ctxt
->sax
->warning
;
444 level
= XML_ERR_WARNING
;
446 if (ctxt
->sax
->initialized
== XML_SAX2_MAGIC
)
447 schannel
= ctxt
->sax
->serror
;
448 data
= ctxt
->userData
;
450 __xmlRaiseError(schannel
, channel
, data
, ctxt
, NULL
, XML_FROM_IO
,
451 XML_IO_LOAD_ERROR
, level
, NULL
, 0,
452 filename
, NULL
, NULL
, 0, 0,
457 /************************************************************************
459 * Tree memory error handler *
461 ************************************************************************/
463 * xmlNormalizeWindowsPath:
464 * @path: the input file path
466 * This function is obsolete. Please see xmlURIFromPath in uri.c for
469 * Returns a canonicalized version of the path
472 xmlNormalizeWindowsPath(const xmlChar
*path
)
474 return xmlCanonicPath(path
);
478 * xmlCleanupInputCallbacks:
480 * clears the entire input callback table. this includes the
484 xmlCleanupInputCallbacks(void)
488 if (!xmlInputCallbackInitialized
)
491 for (i
= xmlInputCallbackNr
- 1; i
>= 0; i
--) {
492 xmlInputCallbackTable
[i
].matchcallback
= NULL
;
493 xmlInputCallbackTable
[i
].opencallback
= NULL
;
494 xmlInputCallbackTable
[i
].readcallback
= NULL
;
495 xmlInputCallbackTable
[i
].closecallback
= NULL
;
498 xmlInputCallbackNr
= 0;
499 xmlInputCallbackInitialized
= 0;
503 * xmlPopInputCallbacks:
505 * Clear the top input callback from the input stack. this includes the
508 * Returns the number of input callback registered or -1 in case of error.
511 xmlPopInputCallbacks(void)
513 if (!xmlInputCallbackInitialized
)
516 if (xmlInputCallbackNr
<= 0)
519 xmlInputCallbackNr
--;
520 xmlInputCallbackTable
[xmlInputCallbackNr
].matchcallback
= NULL
;
521 xmlInputCallbackTable
[xmlInputCallbackNr
].opencallback
= NULL
;
522 xmlInputCallbackTable
[xmlInputCallbackNr
].readcallback
= NULL
;
523 xmlInputCallbackTable
[xmlInputCallbackNr
].closecallback
= NULL
;
525 return(xmlInputCallbackNr
);
528 #ifdef LIBXML_OUTPUT_ENABLED
530 * xmlCleanupOutputCallbacks:
532 * clears the entire output callback table. this includes the
533 * compiled-in I/O callbacks.
536 xmlCleanupOutputCallbacks(void)
540 if (!xmlOutputCallbackInitialized
)
543 for (i
= xmlOutputCallbackNr
- 1; i
>= 0; i
--) {
544 xmlOutputCallbackTable
[i
].matchcallback
= NULL
;
545 xmlOutputCallbackTable
[i
].opencallback
= NULL
;
546 xmlOutputCallbackTable
[i
].writecallback
= NULL
;
547 xmlOutputCallbackTable
[i
].closecallback
= NULL
;
550 xmlOutputCallbackNr
= 0;
551 xmlOutputCallbackInitialized
= 0;
555 * xmlPopOutputCallbacks:
557 * Remove the top output callbacks from the output stack. This includes the
560 * Returns the number of output callback registered or -1 in case of error.
563 xmlPopOutputCallbacks(void)
565 if (!xmlOutputCallbackInitialized
)
568 if (xmlOutputCallbackNr
<= 0)
571 xmlOutputCallbackNr
--;
572 xmlOutputCallbackTable
[xmlOutputCallbackNr
].matchcallback
= NULL
;
573 xmlOutputCallbackTable
[xmlOutputCallbackNr
].opencallback
= NULL
;
574 xmlOutputCallbackTable
[xmlOutputCallbackNr
].writecallback
= NULL
;
575 xmlOutputCallbackTable
[xmlOutputCallbackNr
].closecallback
= NULL
;
577 return(xmlOutputCallbackNr
);
580 #endif /* LIBXML_OUTPUT_ENABLED */
582 /************************************************************************
584 * Standard I/O for file accesses *
586 ************************************************************************/
592 * @path: the path in utf-8 encoding
593 * @mode: type of access (0 - read, 1 - write)
595 * function opens the file specified by @path
599 xmlWrapOpenUtf8(const char *path
,int mode
)
604 wPath
= __xmlIOWin32UTF8ToWChar(path
);
607 fd
= _wfopen(wPath
, mode
? L
"wb" : L
"rb");
610 /* maybe path in native encoding */
612 fd
= fopen(path
, mode
? "wb" : "rb");
617 #ifdef LIBXML_ZLIB_ENABLED
619 xmlWrapGzOpenUtf8(const char *path
, const char *mode
)
624 fd
= gzopen (path
, mode
);
628 wPath
= __xmlIOWin32UTF8ToWChar(path
);
631 int d
, m
= (strstr(mode
, "r") ? O_RDONLY
: O_RDWR
);
633 m
|= (strstr(mode
, "b") ? _O_BINARY
: 0);
635 d
= _wopen(wPath
, m
);
637 fd
= gzdopen(d
, mode
);
647 * @path: the path in utf-8 encoding
648 * @info: structure that stores results
650 * function obtains information about the file or directory
654 xmlWrapStatUtf8(const char *path
, struct _stat
*info
) {
658 wPath
= __xmlIOWin32UTF8ToWChar(path
);
660 retval
= _wstat(wPath
, info
);
663 /* maybe path in native encoding */
665 retval
= _stat(path
, info
);
673 * @path: the path to check
675 * function checks to see if @path is a valid source
676 * (file, socket...) for XML.
678 * if stat is not available on the target machine,
679 * returns 1. if stat fails, returns 0 (if calling
680 * stat on the filename fails, it can't be right).
681 * if stat succeeds and the file is a directory,
682 * returns 2. otherwise returns 1.
686 xmlCheckFilename (const char *path
)
690 struct _stat stat_buffer
;
692 struct stat stat_buffer
;
701 * On Windows stat and wstat do not work with long pathname,
702 * which start with '\\?\'
704 if ((path
[0] == '\\') && (path
[1] == '\\') && (path
[2] == '?') &&
708 if (xmlWrapStatUtf8(path
, &stat_buffer
) == -1)
711 if (stat(path
, &stat_buffer
) == -1)
715 if (S_ISDIR(stat_buffer
.st_mode
))
718 #endif /* HAVE_STAT */
723 * xmlInputReadCallbackNop:
725 * No Operation xmlInputReadCallback function, does nothing.
730 xmlInputReadCallbackNop(void *context ATTRIBUTE_UNUSED
,
731 char *buffer ATTRIBUTE_UNUSED
,
732 int len ATTRIBUTE_UNUSED
) {
738 * @context: the I/O context
739 * @buffer: where to drop data
740 * @len: number of bytes to read
742 * Read @len bytes to @buffer from the I/O channel.
744 * Returns the number of bytes written
747 xmlFdRead (void * context
, char * buffer
, int len
) {
750 ret
= read((int) (ptrdiff_t) context
, &buffer
[0], len
);
751 if (ret
< 0) xmlIOErr(0, "read()");
755 #ifdef LIBXML_OUTPUT_ENABLED
758 * @context: the I/O context
759 * @buffer: where to get data
760 * @len: number of bytes to write
762 * Write @len bytes from @buffer to the I/O channel.
764 * Returns the number of bytes written
767 xmlFdWrite (void * context
, const char * buffer
, int len
) {
771 ret
= write((int) (ptrdiff_t) context
, &buffer
[0], len
);
772 if (ret
< 0) xmlIOErr(0, "write()");
776 #endif /* LIBXML_OUTPUT_ENABLED */
780 * @context: the I/O context
782 * Close an I/O channel
784 * Returns 0 in case of success and error code otherwise
787 xmlFdClose (void * context
) {
789 ret
= close((int) (ptrdiff_t) context
);
790 if (ret
< 0) xmlIOErr(0, "close()");
796 * @filename: the URI for matching
800 * Returns 1 if matches, 0 otherwise
803 xmlFileMatch (const char *filename ATTRIBUTE_UNUSED
) {
809 * @filename: the URI for matching
811 * input from FILE *, supports compressed input
812 * if @filename is " " then the standard input is used
814 * Returns an I/O context or NULL in case of error
817 xmlFileOpen_real (const char *filename
) {
818 const char *path
= filename
;
821 if (filename
== NULL
)
824 if (!strcmp(filename
, "-")) {
829 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17)) {
831 path
= &filename
[17];
833 path
= &filename
[16];
835 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
841 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:/", 6)) {
842 /* lots of generators seems to lazy to read RFC 1738 */
850 /* Do not check DDNAME on zOS ! */
851 #if !defined(__MVS__)
852 if (!xmlCheckFilename(path
))
857 fd
= xmlWrapOpenUtf8(path
, 0);
859 fd
= fopen(path
, "rb");
861 if (fd
== NULL
) xmlIOErr(0, path
);
867 * @filename: the URI for matching
869 * Wrapper around xmlFileOpen_real that try it with an unescaped
870 * version of @filename, if this fails fallback to @filename
872 * Returns a handler or NULL in case or failure
875 xmlFileOpen (const char *filename
) {
879 retval
= xmlFileOpen_real(filename
);
880 if (retval
== NULL
) {
881 unescaped
= xmlURIUnescapeString(filename
, 0, NULL
);
882 if (unescaped
!= NULL
) {
883 retval
= xmlFileOpen_real(unescaped
);
891 #ifdef LIBXML_OUTPUT_ENABLED
894 * @filename: the URI for matching
896 * output to from FILE *,
897 * if @filename is "-" then the standard output is used
899 * Returns an I/O context or NULL in case of error
902 xmlFileOpenW (const char *filename
) {
903 const char *path
= NULL
;
906 if (!strcmp(filename
, "-")) {
911 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17))
913 path
= &filename
[17];
915 path
= &filename
[16];
917 else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
930 fd
= xmlWrapOpenUtf8(path
, 1);
932 fd
= fopen(path
, "w");
934 fd
= fopen(path
, "wb");
937 if (fd
== NULL
) xmlIOErr(0, path
);
940 #endif /* LIBXML_OUTPUT_ENABLED */
944 * @context: the I/O context
945 * @buffer: where to drop data
946 * @len: number of bytes to write
948 * Read @len bytes to @buffer from the I/O channel.
950 * Returns the number of bytes written or < 0 in case of failure
953 xmlFileRead (void * context
, char * buffer
, int len
) {
955 if ((context
== NULL
) || (buffer
== NULL
))
957 ret
= fread(&buffer
[0], 1, len
, (FILE *) context
);
958 if (ret
< 0) xmlIOErr(0, "fread()");
962 #ifdef LIBXML_OUTPUT_ENABLED
965 * @context: the I/O context
966 * @buffer: where to drop data
967 * @len: number of bytes to write
969 * Write @len bytes from @buffer to the I/O channel.
971 * Returns the number of bytes written
974 xmlFileWrite (void * context
, const char * buffer
, int len
) {
977 if ((context
== NULL
) || (buffer
== NULL
))
979 items
= fwrite(&buffer
[0], len
, 1, (FILE *) context
);
980 if ((items
== 0) && (ferror((FILE *) context
))) {
981 xmlIOErr(0, "fwrite()");
986 #endif /* LIBXML_OUTPUT_ENABLED */
990 * @context: the I/O context
992 * Close an I/O channel
994 * Returns 0 or -1 in case of error
997 xmlFileClose (void * context
) {
1001 if (context
== NULL
)
1003 fil
= (FILE *) context
;
1004 if ((fil
== stdout
) || (fil
== stderr
)) {
1007 xmlIOErr(0, "fflush()");
1012 ret
= ( fclose((FILE *) context
) == EOF
) ? -1 : 0;
1014 xmlIOErr(0, "fclose()");
1020 * @context: the I/O context
1022 * Flush an I/O channel
1025 xmlFileFlush (void * context
) {
1028 if (context
== NULL
)
1030 ret
= ( fflush((FILE *) context
) == EOF
) ? -1 : 0;
1032 xmlIOErr(0, "fflush()");
1036 #ifdef LIBXML_OUTPUT_ENABLED
1039 * @context: the xmlBuffer
1040 * @buffer: the data to write
1041 * @len: number of bytes to write
1043 * Write @len bytes from @buffer to the xml buffer
1045 * Returns the number of bytes written
1048 xmlBufferWrite (void * context
, const char * buffer
, int len
) {
1051 ret
= xmlBufferAdd((xmlBufferPtr
) context
, (const xmlChar
*) buffer
, len
);
1058 #ifdef LIBXML_ZLIB_ENABLED
1059 /************************************************************************
1061 * I/O for compressed file accesses *
1063 ************************************************************************/
1066 * @filename: the URI for matching
1068 * input from compressed file test
1070 * Returns 1 if matches, 0 otherwise
1073 xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED
) {
1078 * xmlGzfileOpen_real:
1079 * @filename: the URI for matching
1081 * input from compressed file open
1082 * if @filename is " " then the standard input is used
1084 * Returns an I/O context or NULL in case of error
1087 xmlGzfileOpen_real (const char *filename
) {
1088 const char *path
= NULL
;
1091 if (!strcmp(filename
, "-")) {
1092 int duped_fd
= dup(fileno(stdin
));
1093 fd
= gzdopen(duped_fd
, "rb");
1094 if (fd
== Z_NULL
&& duped_fd
>= 0) {
1095 close(duped_fd
); /* gzdOpen() does not close on failure */
1098 return((void *) fd
);
1101 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17))
1102 #if defined (_WIN32)
1103 path
= &filename
[17];
1105 path
= &filename
[16];
1107 else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
1108 #if defined (_WIN32)
1109 path
= &filename
[8];
1111 path
= &filename
[7];
1118 if (!xmlCheckFilename(path
))
1122 fd
= xmlWrapGzOpenUtf8(path
, "rb");
1124 fd
= gzopen(path
, "rb");
1126 return((void *) fd
);
1131 * @filename: the URI for matching
1133 * Wrapper around xmlGzfileOpen_real if the open fails, it will
1134 * try to unescape @filename
1137 xmlGzfileOpen (const char *filename
) {
1141 retval
= xmlGzfileOpen_real(filename
);
1142 if (retval
== NULL
) {
1143 unescaped
= xmlURIUnescapeString(filename
, 0, NULL
);
1144 if (unescaped
!= NULL
) {
1145 retval
= xmlGzfileOpen_real(unescaped
);
1152 #ifdef LIBXML_OUTPUT_ENABLED
1155 * @filename: the URI for matching
1156 * @compression: the compression factor (0 - 9 included)
1158 * input from compressed file open
1159 * if @filename is " " then the standard input is used
1161 * Returns an I/O context or NULL in case of error
1164 xmlGzfileOpenW (const char *filename
, int compression
) {
1165 const char *path
= NULL
;
1169 snprintf(mode
, sizeof(mode
), "wb%d", compression
);
1170 if (!strcmp(filename
, "-")) {
1171 int duped_fd
= dup(fileno(stdout
));
1172 fd
= gzdopen(duped_fd
, "rb");
1173 if (fd
== Z_NULL
&& duped_fd
>= 0) {
1174 close(duped_fd
); /* gzdOpen() does not close on failure */
1177 return((void *) fd
);
1180 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17))
1181 #if defined (_WIN32)
1182 path
= &filename
[17];
1184 path
= &filename
[16];
1186 else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
1187 #if defined (_WIN32)
1188 path
= &filename
[8];
1190 path
= &filename
[7];
1199 fd
= xmlWrapGzOpenUtf8(path
, mode
);
1201 fd
= gzopen(path
, mode
);
1203 return((void *) fd
);
1205 #endif /* LIBXML_OUTPUT_ENABLED */
1209 * @context: the I/O context
1210 * @buffer: where to drop data
1211 * @len: number of bytes to write
1213 * Read @len bytes to @buffer from the compressed I/O channel.
1215 * Returns the number of bytes read.
1218 xmlGzfileRead (void * context
, char * buffer
, int len
) {
1221 ret
= gzread((gzFile
) context
, &buffer
[0], len
);
1222 if (ret
< 0) xmlIOErr(0, "gzread()");
1226 #ifdef LIBXML_OUTPUT_ENABLED
1229 * @context: the I/O context
1230 * @buffer: where to drop data
1231 * @len: number of bytes to write
1233 * Write @len bytes from @buffer to the compressed I/O channel.
1235 * Returns the number of bytes written
1238 xmlGzfileWrite (void * context
, const char * buffer
, int len
) {
1241 ret
= gzwrite((gzFile
) context
, (char *) &buffer
[0], len
);
1242 if (ret
< 0) xmlIOErr(0, "gzwrite()");
1245 #endif /* LIBXML_OUTPUT_ENABLED */
1249 * @context: the I/O context
1251 * Close a compressed I/O channel
1254 xmlGzfileClose (void * context
) {
1257 ret
= (gzclose((gzFile
) context
) == Z_OK
) ? 0 : -1;
1258 if (ret
< 0) xmlIOErr(0, "gzclose()");
1261 #endif /* LIBXML_ZLIB_ENABLED */
1263 #ifdef LIBXML_LZMA_ENABLED
1264 /************************************************************************
1266 * I/O for compressed file accesses *
1268 ************************************************************************/
1272 * @filename: the URI for matching
1274 * input from compressed file test
1276 * Returns 1 if matches, 0 otherwise
1279 xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED
) {
1284 * xmlXzFileOpen_real:
1285 * @filename: the URI for matching
1287 * input from compressed file open
1288 * if @filename is " " then the standard input is used
1290 * Returns an I/O context or NULL in case of error
1293 xmlXzfileOpen_real (const char *filename
) {
1294 const char *path
= NULL
;
1297 if (!strcmp(filename
, "-")) {
1298 fd
= __libxml2_xzdopen(dup(fileno(stdin
)), "rb");
1299 return((void *) fd
);
1302 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17)) {
1303 path
= &filename
[16];
1304 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
1305 path
= &filename
[7];
1306 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:/", 6)) {
1307 /* lots of generators seems to lazy to read RFC 1738 */
1308 path
= &filename
[5];
1314 if (!xmlCheckFilename(path
))
1317 fd
= __libxml2_xzopen(path
, "rb");
1318 return((void *) fd
);
1323 * @filename: the URI for matching
1325 * Wrapper around xmlXzfileOpen_real that try it with an unescaped
1326 * version of @filename, if this fails fallback to @filename
1328 * Returns a handler or NULL in case or failure
1331 xmlXzfileOpen (const char *filename
) {
1335 retval
= xmlXzfileOpen_real(filename
);
1336 if (retval
== NULL
) {
1337 unescaped
= xmlURIUnescapeString(filename
, 0, NULL
);
1338 if (unescaped
!= NULL
) {
1339 retval
= xmlXzfileOpen_real(unescaped
);
1349 * @context: the I/O context
1350 * @buffer: where to drop data
1351 * @len: number of bytes to write
1353 * Read @len bytes to @buffer from the compressed I/O channel.
1355 * Returns the number of bytes written
1358 xmlXzfileRead (void * context
, char * buffer
, int len
) {
1361 ret
= __libxml2_xzread((xzFile
) context
, &buffer
[0], len
);
1362 if (ret
< 0) xmlIOErr(0, "xzread()");
1368 * @context: the I/O context
1370 * Close a compressed I/O channel
1373 xmlXzfileClose (void * context
) {
1376 ret
= (__libxml2_xzclose((xzFile
) context
) == LZMA_OK
) ? 0 : -1;
1377 if (ret
< 0) xmlIOErr(0, "xzclose()");
1380 #endif /* LIBXML_LZMA_ENABLED */
1382 #ifdef LIBXML_HTTP_ENABLED
1383 /************************************************************************
1385 * I/O for HTTP file accesses *
1387 ************************************************************************/
1389 #ifdef LIBXML_OUTPUT_ENABLED
1390 typedef struct xmlIOHTTPWriteCtxt_
1398 } xmlIOHTTPWriteCtxt
, *xmlIOHTTPWriteCtxtPtr
;
1400 #ifdef LIBXML_ZLIB_ENABLED
1402 #define DFLT_WBITS ( -15 )
1403 #define DFLT_MEM_LVL ( 8 )
1404 #define GZ_MAGIC1 ( 0x1f )
1405 #define GZ_MAGIC2 ( 0x8b )
1406 #define LXML_ZLIB_OS_CODE ( 0x03 )
1407 #define INIT_HTTP_BUFF_SIZE ( 32768 )
1408 #define DFLT_ZLIB_RATIO ( 5 )
1411 ** Data structure and functions to work with sending compressed data
1415 typedef struct xmlZMemBuff_
1420 unsigned char * zbuff
;
1423 } xmlZMemBuff
, *xmlZMemBuffPtr
;
1426 * append_reverse_ulong
1427 * @buff: Compressed memory buffer
1428 * @data: Unsigned long to append
1430 * Append a unsigned long in reverse byte order to the end of the
1434 append_reverse_ulong( xmlZMemBuff
* buff
, unsigned long data
) {
1442 ** This is plagiarized from putLong in gzio.c (zlib source) where
1443 ** the number "4" is hardcoded. If zlib is ever patched to
1444 ** support 64 bit file sizes, this code would need to be patched
1448 for ( idx
= 0; idx
< 4; idx
++ ) {
1449 *buff
->zctrl
.next_out
= ( data
& 0xff );
1451 buff
->zctrl
.next_out
++;
1460 * @buff: The memory buffer context to clear
1462 * Release all the resources associated with the compressed memory buffer.
1465 xmlFreeZMemBuff( xmlZMemBuffPtr buff
) {
1474 xmlFree( buff
->zbuff
);
1476 z_err
= deflateEnd( &buff
->zctrl
);
1477 if ( z_err
!= Z_OK
)
1478 xmlGenericError( xmlGenericErrorContext
,
1479 "xmlFreeZMemBuff: Error releasing zlib context: %d\n",
1482 deflateEnd( &buff
->zctrl
);
1491 *@compression: Compression value to use
1493 * Create a memory buffer to hold the compressed XML document. The
1494 * compressed document in memory will end up being identical to what
1495 * would be created if gzopen/gzwrite/gzclose were being used to
1496 * write the document to disk. The code for the header/trailer data to
1497 * the compression is plagiarized from the zlib source files.
1500 xmlCreateZMemBuff( int compression
) {
1504 xmlZMemBuffPtr buff
= NULL
;
1506 if ( ( compression
< 1 ) || ( compression
> 9 ) )
1509 /* Create the control and data areas */
1511 buff
= xmlMalloc( sizeof( xmlZMemBuff
) );
1512 if ( buff
== NULL
) {
1513 xmlIOErrMemory("creating buffer context");
1517 (void)memset( buff
, 0, sizeof( xmlZMemBuff
) );
1518 buff
->size
= INIT_HTTP_BUFF_SIZE
;
1519 buff
->zbuff
= xmlMalloc( buff
->size
);
1520 if ( buff
->zbuff
== NULL
) {
1521 xmlFreeZMemBuff( buff
);
1522 xmlIOErrMemory("creating buffer");
1526 z_err
= deflateInit2( &buff
->zctrl
, compression
, Z_DEFLATED
,
1527 DFLT_WBITS
, DFLT_MEM_LVL
, Z_DEFAULT_STRATEGY
);
1528 if ( z_err
!= Z_OK
) {
1530 xmlFreeZMemBuff( buff
);
1532 xmlStrPrintf(msg
, 500,
1533 "xmlCreateZMemBuff: %s %d\n",
1534 "Error initializing compression context. ZLIB error:",
1536 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1540 /* Set the header data. The CRC will be needed for the trailer */
1541 buff
->crc
= crc32( 0L, NULL
, 0 );
1542 hdr_lgth
= snprintf( (char *)buff
->zbuff
, buff
->size
,
1543 "%c%c%c%c%c%c%c%c%c%c",
1544 GZ_MAGIC1
, GZ_MAGIC2
, Z_DEFLATED
,
1545 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE
);
1546 buff
->zctrl
.next_out
= buff
->zbuff
+ hdr_lgth
;
1547 buff
->zctrl
.avail_out
= buff
->size
- hdr_lgth
;
1554 * @buff: Buffer used to compress and consolidate data.
1555 * @ext_amt: Number of bytes to extend the buffer.
1557 * Extend the internal buffer used to store the compressed data by the
1560 * Returns 0 on success or -1 on failure to extend the buffer. On failure
1561 * the original buffer still exists at the original size.
1564 xmlZMemBuffExtend( xmlZMemBuffPtr buff
, size_t ext_amt
) {
1570 unsigned char * tmp_ptr
= NULL
;
1575 else if ( ext_amt
== 0 )
1578 cur_used
= buff
->zctrl
.next_out
- buff
->zbuff
;
1579 new_size
= buff
->size
+ ext_amt
;
1582 if ( cur_used
> new_size
)
1583 xmlGenericError( xmlGenericErrorContext
,
1584 "xmlZMemBuffExtend: %s\n%s %d bytes.\n",
1585 "Buffer overwrite detected during compressed memory",
1586 "buffer extension. Overflowed by",
1587 (cur_used
- new_size
) );
1590 tmp_ptr
= xmlRealloc( buff
->zbuff
, new_size
);
1591 if ( tmp_ptr
!= NULL
) {
1593 buff
->size
= new_size
;
1594 buff
->zbuff
= tmp_ptr
;
1595 buff
->zctrl
.next_out
= tmp_ptr
+ cur_used
;
1596 buff
->zctrl
.avail_out
= new_size
- cur_used
;
1600 xmlStrPrintf(msg
, 500,
1601 "xmlZMemBuffExtend: %s %lu bytes.\n",
1602 "Allocation failure extending output buffer to",
1603 (unsigned long) new_size
);
1604 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1612 * @buff: Buffer used to compress and consolidate data
1613 * @src: Uncompressed source content to append to buffer
1614 * @len: Length of source data to append to buffer
1616 * Compress and append data to the internal buffer. The data buffer
1617 * will be expanded if needed to store the additional data.
1619 * Returns the number of bytes appended to the buffer or -1 on error.
1622 xmlZMemBuffAppend( xmlZMemBuffPtr buff
, const char * src
, int len
) {
1627 if ( ( buff
== NULL
) || ( src
== NULL
) )
1630 buff
->zctrl
.avail_in
= len
;
1631 buff
->zctrl
.next_in
= (unsigned char *)src
;
1632 while ( buff
->zctrl
.avail_in
> 0 ) {
1634 ** Extend the buffer prior to deflate call if a reasonable amount
1635 ** of output buffer space is not available.
1637 min_accept
= buff
->zctrl
.avail_in
/ DFLT_ZLIB_RATIO
;
1638 if ( buff
->zctrl
.avail_out
<= min_accept
) {
1639 if ( xmlZMemBuffExtend( buff
, buff
->size
) == -1 )
1643 z_err
= deflate( &buff
->zctrl
, Z_NO_FLUSH
);
1644 if ( z_err
!= Z_OK
) {
1646 xmlStrPrintf(msg
, 500,
1647 "xmlZMemBuffAppend: %s %d %s - %d",
1648 "Compression error while appending",
1649 len
, "bytes to buffer. ZLIB error", z_err
);
1650 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1655 buff
->crc
= crc32( buff
->crc
, (unsigned char *)src
, len
);
1661 * xmlZMemBuffGetContent
1662 * @buff: Compressed memory content buffer
1663 * @data_ref: Pointer reference to point to compressed content
1665 * Flushes the compression buffers, appends gzip file trailers and
1666 * returns the compressed content and length of the compressed data.
1667 * NOTE: The gzip trailer code here is plagiarized from zlib source.
1669 * Returns the length of the compressed data or -1 on error.
1672 xmlZMemBuffGetContent( xmlZMemBuffPtr buff
, char ** data_ref
) {
1677 if ( ( buff
== NULL
) || ( data_ref
== NULL
) )
1680 /* Need to loop until compression output buffers are flushed */
1684 z_err
= deflate( &buff
->zctrl
, Z_FINISH
);
1685 if ( z_err
== Z_OK
) {
1686 /* In this case Z_OK means more buffer space needed */
1688 if ( xmlZMemBuffExtend( buff
, buff
->size
) == -1 )
1692 while ( z_err
== Z_OK
);
1694 /* If the compression state is not Z_STREAM_END, some error occurred */
1696 if ( z_err
== Z_STREAM_END
) {
1698 /* Need to append the gzip data trailer */
1700 if ( buff
->zctrl
.avail_out
< ( 2 * sizeof( unsigned long ) ) ) {
1701 if ( xmlZMemBuffExtend(buff
, (2 * sizeof(unsigned long))) == -1 )
1706 ** For whatever reason, the CRC and length data are pushed out
1707 ** in reverse byte order. So a memcpy can't be used here.
1710 append_reverse_ulong( buff
, buff
->crc
);
1711 append_reverse_ulong( buff
, buff
->zctrl
.total_in
);
1713 zlgth
= buff
->zctrl
.next_out
- buff
->zbuff
;
1714 *data_ref
= (char *)buff
->zbuff
;
1719 xmlStrPrintf(msg
, 500,
1720 "xmlZMemBuffGetContent: %s - %d\n",
1721 "Error flushing zlib buffers. Error code", z_err
);
1722 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1727 #endif /* LIBXML_OUTPUT_ENABLED */
1728 #endif /* LIBXML_ZLIB_ENABLED */
1730 #ifdef LIBXML_OUTPUT_ENABLED
1732 * xmlFreeHTTPWriteCtxt
1733 * @ctxt: Context to cleanup
1735 * Free allocated memory and reclaim system resources.
1740 xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt
)
1742 if ( ctxt
->uri
!= NULL
)
1743 xmlFree( ctxt
->uri
);
1745 if ( ctxt
->doc_buff
!= NULL
) {
1747 #ifdef LIBXML_ZLIB_ENABLED
1748 if ( ctxt
->compression
> 0 ) {
1749 xmlFreeZMemBuff( ctxt
->doc_buff
);
1754 xmlOutputBufferClose( ctxt
->doc_buff
);
1761 #endif /* LIBXML_OUTPUT_ENABLED */
1766 * @filename: the URI for matching
1768 * check if the URI matches an HTTP one
1770 * Returns 1 if matches, 0 otherwise
1773 xmlIOHTTPMatch (const char *filename
) {
1774 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"http://", 7))
1781 * @filename: the URI for matching
1783 * open an HTTP I/O channel
1785 * Returns an I/O context or NULL in case of error
1788 xmlIOHTTPOpen (const char *filename
) {
1789 return(xmlNanoHTTPOpen(filename
, NULL
));
1792 #ifdef LIBXML_OUTPUT_ENABLED
1795 * @post_uri: The destination URI for the document
1796 * @compression: The compression desired for the document.
1798 * Open a temporary buffer to collect the document for a subsequent HTTP POST
1799 * request. Non-static as is called from the output buffer creation routine.
1801 * Returns an I/O context or NULL in case of error.
1805 xmlIOHTTPOpenW(const char *post_uri
, int compression ATTRIBUTE_UNUSED
)
1808 xmlIOHTTPWriteCtxtPtr ctxt
= NULL
;
1810 if (post_uri
== NULL
)
1813 ctxt
= xmlMalloc(sizeof(xmlIOHTTPWriteCtxt
));
1815 xmlIOErrMemory("creating HTTP output context");
1819 (void) memset(ctxt
, 0, sizeof(xmlIOHTTPWriteCtxt
));
1821 ctxt
->uri
= (char *) xmlStrdup((const xmlChar
*)post_uri
);
1822 if (ctxt
->uri
== NULL
) {
1823 xmlIOErrMemory("copying URI");
1824 xmlFreeHTTPWriteCtxt(ctxt
);
1829 * ** Since the document length is required for an HTTP post,
1830 * ** need to put the document into a buffer. A memory buffer
1831 * ** is being used to avoid pushing the data to disk and back.
1834 #ifdef LIBXML_ZLIB_ENABLED
1835 if ((compression
> 0) && (compression
<= 9)) {
1837 ctxt
->compression
= compression
;
1838 ctxt
->doc_buff
= xmlCreateZMemBuff(compression
);
1842 /* Any character conversions should have been done before this */
1844 ctxt
->doc_buff
= xmlAllocOutputBufferInternal(NULL
);
1847 if (ctxt
->doc_buff
== NULL
) {
1848 xmlFreeHTTPWriteCtxt(ctxt
);
1854 #endif /* LIBXML_OUTPUT_ENABLED */
1856 #ifdef LIBXML_OUTPUT_ENABLED
1858 * xmlIOHTTPDfltOpenW
1859 * @post_uri: The destination URI for this document.
1861 * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
1862 * HTTP post command. This function should generally not be used as
1863 * the open callback is short circuited in xmlOutputBufferCreateFile.
1865 * Returns a pointer to the new IO context.
1868 xmlIOHTTPDfltOpenW( const char * post_uri
) {
1869 return ( xmlIOHTTPOpenW( post_uri
, 0 ) );
1871 #endif /* LIBXML_OUTPUT_ENABLED */
1875 * @context: the I/O context
1876 * @buffer: where to drop data
1877 * @len: number of bytes to write
1879 * Read @len bytes to @buffer from the I/O channel.
1881 * Returns the number of bytes written
1884 xmlIOHTTPRead(void * context
, char * buffer
, int len
) {
1885 if ((buffer
== NULL
) || (len
< 0)) return(-1);
1886 return(xmlNanoHTTPRead(context
, &buffer
[0], len
));
1889 #ifdef LIBXML_OUTPUT_ENABLED
1892 * @context: previously opened writing context
1893 * @buffer: data to output to temporary buffer
1894 * @len: bytes to output
1896 * Collect data from memory buffer into a temporary file for later
1899 * Returns number of bytes written.
1903 xmlIOHTTPWrite( void * context
, const char * buffer
, int len
) {
1905 xmlIOHTTPWriteCtxtPtr ctxt
= context
;
1907 if ( ( ctxt
== NULL
) || ( ctxt
->doc_buff
== NULL
) || ( buffer
== NULL
) )
1912 /* Use gzwrite or fwrite as previously setup in the open call */
1914 #ifdef LIBXML_ZLIB_ENABLED
1915 if ( ctxt
->compression
> 0 )
1916 len
= xmlZMemBuffAppend( ctxt
->doc_buff
, buffer
, len
);
1920 len
= xmlOutputBufferWrite( ctxt
->doc_buff
, len
, buffer
);
1924 xmlStrPrintf(msg
, 500,
1925 "xmlIOHTTPWrite: %s\n%s '%s'.\n",
1926 "Error appending to internal buffer.",
1927 "Error sending document to URI",
1929 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1935 #endif /* LIBXML_OUTPUT_ENABLED */
1940 * @context: the I/O context
1942 * Close an HTTP I/O channel
1947 xmlIOHTTPClose (void * context
) {
1948 xmlNanoHTTPClose(context
);
1952 #ifdef LIBXML_OUTPUT_ENABLED
1954 * xmlIOHTTCloseWrite
1955 * @context: The I/O context
1956 * @http_mthd: The HTTP method to be used when sending the data
1958 * Close the transmit HTTP I/O channel and actually send the data.
1961 xmlIOHTTPCloseWrite( void * context
, const char * http_mthd
) {
1965 int content_lgth
= 0;
1966 xmlIOHTTPWriteCtxtPtr ctxt
= context
;
1968 char * http_content
= NULL
;
1969 char * content_encoding
= NULL
;
1970 char * content_type
= (char *) "text/xml";
1971 void * http_ctxt
= NULL
;
1973 if ( ( ctxt
== NULL
) || ( http_mthd
== NULL
) )
1976 /* Retrieve the content from the appropriate buffer */
1978 #ifdef LIBXML_ZLIB_ENABLED
1980 if ( ctxt
->compression
> 0 ) {
1981 content_lgth
= xmlZMemBuffGetContent( ctxt
->doc_buff
, &http_content
);
1982 content_encoding
= (char *) "Content-Encoding: gzip";
1987 /* Pull the data out of the memory output buffer */
1989 xmlOutputBufferPtr dctxt
= ctxt
->doc_buff
;
1990 http_content
= (char *) xmlBufContent(dctxt
->buffer
);
1991 content_lgth
= xmlBufUse(dctxt
->buffer
);
1994 if ( http_content
== NULL
) {
1996 xmlStrPrintf(msg
, 500,
1997 "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
1998 "Error retrieving content.\nUnable to",
1999 http_mthd
, "data to URI", ctxt
->uri
);
2000 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
2005 http_ctxt
= xmlNanoHTTPMethod( ctxt
->uri
, http_mthd
, http_content
,
2006 &content_type
, content_encoding
,
2009 if ( http_ctxt
!= NULL
) {
2011 /* If testing/debugging - dump reply with request content */
2013 FILE * tst_file
= NULL
;
2014 char buffer
[ 4096 ];
2015 char * dump_name
= NULL
;
2018 xmlGenericError( xmlGenericErrorContext
,
2019 "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n",
2020 http_mthd
, ctxt
->uri
,
2021 xmlNanoHTTPReturnCode( http_ctxt
) );
2024 ** Since either content or reply may be gzipped,
2025 ** dump them to separate files instead of the
2026 ** standard error context.
2029 dump_name
= tempnam( NULL
, "lxml" );
2030 if ( dump_name
!= NULL
) {
2031 (void)snprintf( buffer
, sizeof(buffer
), "%s.content", dump_name
);
2033 tst_file
= fopen( buffer
, "wb" );
2034 if ( tst_file
!= NULL
) {
2035 xmlGenericError( xmlGenericErrorContext
,
2036 "Transmitted content saved in file: %s\n", buffer
);
2038 fwrite( http_content
, sizeof( char ),
2039 content_lgth
, tst_file
);
2043 (void)snprintf( buffer
, sizeof(buffer
), "%s.reply", dump_name
);
2044 tst_file
= fopen( buffer
, "wb" );
2045 if ( tst_file
!= NULL
) {
2046 xmlGenericError( xmlGenericErrorContext
,
2047 "Reply content saved in file: %s\n", buffer
);
2050 while ( (avail
= xmlNanoHTTPRead( http_ctxt
,
2051 buffer
, sizeof( buffer
) )) > 0 ) {
2053 fwrite( buffer
, sizeof( char ), avail
, tst_file
);
2061 #endif /* DEBUG_HTTP */
2063 http_rtn
= xmlNanoHTTPReturnCode( http_ctxt
);
2064 if ( ( http_rtn
>= 200 ) && ( http_rtn
< 300 ) )
2068 xmlStrPrintf(msg
, 500,
2069 "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
2070 http_mthd
, content_lgth
,
2071 "bytes to URI", ctxt
->uri
,
2072 "failed. HTTP return code:", http_rtn
);
2073 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
2076 xmlNanoHTTPClose( http_ctxt
);
2077 xmlFree( content_type
);
2081 /* Final cleanups */
2083 xmlFreeHTTPWriteCtxt( ctxt
);
2085 return ( close_rc
);
2091 * @context: The I/O context
2093 * Close the transmit HTTP I/O channel and actually send data using a PUT
2097 xmlIOHTTPClosePut( void * ctxt
) {
2098 return ( xmlIOHTTPCloseWrite( ctxt
, "PUT" ) );
2103 * xmlIOHTTPClosePost
2105 * @context: The I/O context
2107 * Close the transmit HTTP I/O channel and actually send data using a POST
2111 xmlIOHTTPClosePost( void * ctxt
) {
2112 return ( xmlIOHTTPCloseWrite( ctxt
, "POST" ) );
2114 #endif /* LIBXML_OUTPUT_ENABLED */
2116 #endif /* LIBXML_HTTP_ENABLED */
2118 #ifdef LIBXML_FTP_ENABLED
2119 /************************************************************************
2121 * I/O for FTP file accesses *
2123 ************************************************************************/
2126 * @filename: the URI for matching
2128 * check if the URI matches an FTP one
2130 * Returns 1 if matches, 0 otherwise
2133 xmlIOFTPMatch (const char *filename
) {
2134 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"ftp://", 6))
2141 * @filename: the URI for matching
2143 * open an FTP I/O channel
2145 * Returns an I/O context or NULL in case of error
2148 xmlIOFTPOpen (const char *filename
) {
2149 return(xmlNanoFTPOpen(filename
));
2154 * @context: the I/O context
2155 * @buffer: where to drop data
2156 * @len: number of bytes to write
2158 * Read @len bytes to @buffer from the I/O channel.
2160 * Returns the number of bytes written
2163 xmlIOFTPRead(void * context
, char * buffer
, int len
) {
2164 if ((buffer
== NULL
) || (len
< 0)) return(-1);
2165 return(xmlNanoFTPRead(context
, &buffer
[0], len
));
2170 * @context: the I/O context
2172 * Close an FTP I/O channel
2177 xmlIOFTPClose (void * context
) {
2178 return ( xmlNanoFTPClose(context
) );
2180 #endif /* LIBXML_FTP_ENABLED */
2184 * xmlRegisterInputCallbacks:
2185 * @matchFunc: the xmlInputMatchCallback
2186 * @openFunc: the xmlInputOpenCallback
2187 * @readFunc: the xmlInputReadCallback
2188 * @closeFunc: the xmlInputCloseCallback
2190 * Register a new set of I/O callback for handling parser input.
2192 * Returns the registered handler number or -1 in case of error
2195 xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc
,
2196 xmlInputOpenCallback openFunc
, xmlInputReadCallback readFunc
,
2197 xmlInputCloseCallback closeFunc
) {
2198 if (xmlInputCallbackNr
>= MAX_INPUT_CALLBACK
) {
2201 xmlInputCallbackTable
[xmlInputCallbackNr
].matchcallback
= matchFunc
;
2202 xmlInputCallbackTable
[xmlInputCallbackNr
].opencallback
= openFunc
;
2203 xmlInputCallbackTable
[xmlInputCallbackNr
].readcallback
= readFunc
;
2204 xmlInputCallbackTable
[xmlInputCallbackNr
].closecallback
= closeFunc
;
2205 xmlInputCallbackInitialized
= 1;
2206 return(xmlInputCallbackNr
++);
2209 #ifdef LIBXML_OUTPUT_ENABLED
2211 * xmlRegisterOutputCallbacks:
2212 * @matchFunc: the xmlOutputMatchCallback
2213 * @openFunc: the xmlOutputOpenCallback
2214 * @writeFunc: the xmlOutputWriteCallback
2215 * @closeFunc: the xmlOutputCloseCallback
2217 * Register a new set of I/O callback for handling output.
2219 * Returns the registered handler number or -1 in case of error
2222 xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc
,
2223 xmlOutputOpenCallback openFunc
, xmlOutputWriteCallback writeFunc
,
2224 xmlOutputCloseCallback closeFunc
) {
2225 if (xmlOutputCallbackNr
>= MAX_OUTPUT_CALLBACK
) {
2228 xmlOutputCallbackTable
[xmlOutputCallbackNr
].matchcallback
= matchFunc
;
2229 xmlOutputCallbackTable
[xmlOutputCallbackNr
].opencallback
= openFunc
;
2230 xmlOutputCallbackTable
[xmlOutputCallbackNr
].writecallback
= writeFunc
;
2231 xmlOutputCallbackTable
[xmlOutputCallbackNr
].closecallback
= closeFunc
;
2232 xmlOutputCallbackInitialized
= 1;
2233 return(xmlOutputCallbackNr
++);
2235 #endif /* LIBXML_OUTPUT_ENABLED */
2238 * xmlRegisterDefaultInputCallbacks:
2240 * Registers the default compiled-in I/O handlers.
2243 xmlRegisterDefaultInputCallbacks(void) {
2244 if (xmlInputCallbackInitialized
)
2247 xmlRegisterInputCallbacks(xmlFileMatch
, xmlFileOpen
,
2248 xmlFileRead
, xmlFileClose
);
2249 #ifdef LIBXML_ZLIB_ENABLED
2250 xmlRegisterInputCallbacks(xmlGzfileMatch
, xmlGzfileOpen
,
2251 xmlGzfileRead
, xmlGzfileClose
);
2252 #endif /* LIBXML_ZLIB_ENABLED */
2253 #ifdef LIBXML_LZMA_ENABLED
2254 xmlRegisterInputCallbacks(xmlXzfileMatch
, xmlXzfileOpen
,
2255 xmlXzfileRead
, xmlXzfileClose
);
2256 #endif /* LIBXML_LZMA_ENABLED */
2258 #ifdef LIBXML_HTTP_ENABLED
2259 xmlRegisterInputCallbacks(xmlIOHTTPMatch
, xmlIOHTTPOpen
,
2260 xmlIOHTTPRead
, xmlIOHTTPClose
);
2261 #endif /* LIBXML_HTTP_ENABLED */
2263 #ifdef LIBXML_FTP_ENABLED
2264 xmlRegisterInputCallbacks(xmlIOFTPMatch
, xmlIOFTPOpen
,
2265 xmlIOFTPRead
, xmlIOFTPClose
);
2266 #endif /* LIBXML_FTP_ENABLED */
2267 xmlInputCallbackInitialized
= 1;
2270 #ifdef LIBXML_OUTPUT_ENABLED
2272 * xmlRegisterDefaultOutputCallbacks:
2274 * Registers the default compiled-in I/O handlers.
2277 xmlRegisterDefaultOutputCallbacks (void) {
2278 if (xmlOutputCallbackInitialized
)
2281 xmlRegisterOutputCallbacks(xmlFileMatch
, xmlFileOpenW
,
2282 xmlFileWrite
, xmlFileClose
);
2284 #ifdef LIBXML_HTTP_ENABLED
2285 xmlRegisterOutputCallbacks(xmlIOHTTPMatch
, xmlIOHTTPDfltOpenW
,
2286 xmlIOHTTPWrite
, xmlIOHTTPClosePut
);
2289 /*********************************
2290 No way a-priori to distinguish between gzipped files from
2291 uncompressed ones except opening if existing then closing
2292 and saving with same compression ratio ... a pain.
2294 #ifdef LIBXML_ZLIB_ENABLED
2295 xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2296 xmlGzfileWrite, xmlGzfileClose);
2300 #ifdef LIBXML_FTP_ENABLED
2301 xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2302 xmlIOFTPWrite, xmlIOFTPClose);
2304 **********************************/
2305 xmlOutputCallbackInitialized
= 1;
2308 #ifdef LIBXML_HTTP_ENABLED
2310 * xmlRegisterHTTPPostCallbacks:
2312 * By default, libxml submits HTTP output requests using the "PUT" method.
2313 * Calling this method changes the HTTP output method to use the "POST"
2318 xmlRegisterHTTPPostCallbacks( void ) {
2320 /* Register defaults if not done previously */
2322 if ( xmlOutputCallbackInitialized
== 0 )
2323 xmlRegisterDefaultOutputCallbacks( );
2325 xmlRegisterOutputCallbacks(xmlIOHTTPMatch
, xmlIOHTTPDfltOpenW
,
2326 xmlIOHTTPWrite
, xmlIOHTTPClosePost
);
2330 #endif /* LIBXML_OUTPUT_ENABLED */
2333 * xmlAllocParserInputBuffer:
2334 * @enc: the charset encoding if known
2336 * Create a buffered parser input for progressive parsing
2338 * Returns the new parser input or NULL
2340 xmlParserInputBufferPtr
2341 xmlAllocParserInputBuffer(xmlCharEncoding enc
) {
2342 xmlParserInputBufferPtr ret
;
2344 ret
= (xmlParserInputBufferPtr
) xmlMalloc(sizeof(xmlParserInputBuffer
));
2346 xmlIOErrMemory("creating input buffer");
2349 memset(ret
, 0, (size_t) sizeof(xmlParserInputBuffer
));
2350 ret
->buffer
= xmlBufCreateSize(2 * xmlDefaultBufferSize
);
2351 if (ret
->buffer
== NULL
) {
2355 xmlBufSetAllocationScheme(ret
->buffer
, XML_BUFFER_ALLOC_DOUBLEIT
);
2356 ret
->encoder
= xmlGetCharEncodingHandler(enc
);
2357 if (ret
->encoder
!= NULL
)
2358 ret
->raw
= xmlBufCreateSize(2 * xmlDefaultBufferSize
);
2361 ret
->readcallback
= NULL
;
2362 ret
->closecallback
= NULL
;
2363 ret
->context
= NULL
;
2364 ret
->compressed
= -1;
2365 ret
->rawconsumed
= 0;
2370 #ifdef LIBXML_OUTPUT_ENABLED
2372 * xmlAllocOutputBuffer:
2373 * @encoder: the encoding converter or NULL
2375 * Create a buffered parser output
2377 * Returns the new parser output or NULL
2380 xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder
) {
2381 xmlOutputBufferPtr ret
;
2383 ret
= (xmlOutputBufferPtr
) xmlMalloc(sizeof(xmlOutputBuffer
));
2385 xmlIOErrMemory("creating output buffer");
2388 memset(ret
, 0, (size_t) sizeof(xmlOutputBuffer
));
2389 ret
->buffer
= xmlBufCreate();
2390 if (ret
->buffer
== NULL
) {
2394 xmlBufSetAllocationScheme(ret
->buffer
, XML_BUFFER_ALLOC_DOUBLEIT
);
2396 ret
->encoder
= encoder
;
2397 if (encoder
!= NULL
) {
2398 ret
->conv
= xmlBufCreateSize(4000);
2399 if (ret
->conv
== NULL
) {
2400 xmlBufFree(ret
->buffer
);
2406 * This call is designed to initiate the encoder state
2408 xmlCharEncOutput(ret
, 1);
2411 ret
->writecallback
= NULL
;
2412 ret
->closecallback
= NULL
;
2413 ret
->context
= NULL
;
2420 * xmlAllocOutputBufferInternal:
2421 * @encoder: the encoding converter or NULL
2423 * Create a buffered parser output
2425 * Returns the new parser output or NULL
2428 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder
) {
2429 xmlOutputBufferPtr ret
;
2431 ret
= (xmlOutputBufferPtr
) xmlMalloc(sizeof(xmlOutputBuffer
));
2433 xmlIOErrMemory("creating output buffer");
2436 memset(ret
, 0, (size_t) sizeof(xmlOutputBuffer
));
2437 ret
->buffer
= xmlBufCreate();
2438 if (ret
->buffer
== NULL
) {
2445 * For conversion buffers we use the special IO handling
2447 xmlBufSetAllocationScheme(ret
->buffer
, XML_BUFFER_ALLOC_IO
);
2449 ret
->encoder
= encoder
;
2450 if (encoder
!= NULL
) {
2451 ret
->conv
= xmlBufCreateSize(4000);
2452 if (ret
->conv
== NULL
) {
2453 xmlBufFree(ret
->buffer
);
2459 * This call is designed to initiate the encoder state
2461 xmlCharEncOutput(ret
, 1);
2464 ret
->writecallback
= NULL
;
2465 ret
->closecallback
= NULL
;
2466 ret
->context
= NULL
;
2472 #endif /* LIBXML_OUTPUT_ENABLED */
2475 * xmlFreeParserInputBuffer:
2476 * @in: a buffered parser input
2478 * Free up the memory used by a buffered parser input
2481 xmlFreeParserInputBuffer(xmlParserInputBufferPtr in
) {
2482 if (in
== NULL
) return;
2485 xmlBufFree(in
->raw
);
2488 if (in
->encoder
!= NULL
) {
2489 xmlCharEncCloseFunc(in
->encoder
);
2491 if (in
->closecallback
!= NULL
) {
2492 in
->closecallback(in
->context
);
2494 if (in
->buffer
!= NULL
) {
2495 xmlBufFree(in
->buffer
);
2502 #ifdef LIBXML_OUTPUT_ENABLED
2504 * xmlOutputBufferClose:
2505 * @out: a buffered output
2507 * flushes and close the output I/O channel
2508 * and free up all the associated resources
2510 * Returns the number of byte written or -1 in case of error.
2513 xmlOutputBufferClose(xmlOutputBufferPtr out
)
2520 if (out
->writecallback
!= NULL
)
2521 xmlOutputBufferFlush(out
);
2522 if (out
->closecallback
!= NULL
) {
2523 err_rc
= out
->closecallback(out
->context
);
2525 written
= out
->written
;
2527 xmlBufFree(out
->conv
);
2530 if (out
->encoder
!= NULL
) {
2531 xmlCharEncCloseFunc(out
->encoder
);
2533 if (out
->buffer
!= NULL
) {
2534 xmlBufFree(out
->buffer
);
2541 return ((err_rc
== 0) ? written
: err_rc
);
2543 #endif /* LIBXML_OUTPUT_ENABLED */
2545 xmlParserInputBufferPtr
2546 __xmlParserInputBufferCreateFilename(const char *URI
, xmlCharEncoding enc
) {
2547 xmlParserInputBufferPtr ret
;
2549 void *context
= NULL
;
2551 if (xmlInputCallbackInitialized
== 0)
2552 xmlRegisterDefaultInputCallbacks();
2554 if (URI
== NULL
) return(NULL
);
2557 * Try to find one of the input accept method accepting that scheme
2558 * Go in reverse to give precedence to user defined handlers.
2560 if (context
== NULL
) {
2561 for (i
= xmlInputCallbackNr
- 1;i
>= 0;i
--) {
2562 if ((xmlInputCallbackTable
[i
].matchcallback
!= NULL
) &&
2563 (xmlInputCallbackTable
[i
].matchcallback(URI
) != 0)) {
2564 context
= xmlInputCallbackTable
[i
].opencallback(URI
);
2565 if (context
!= NULL
) {
2571 if (context
== NULL
) {
2576 * Allocate the Input buffer front-end.
2578 ret
= xmlAllocParserInputBuffer(enc
);
2580 ret
->context
= context
;
2581 ret
->readcallback
= xmlInputCallbackTable
[i
].readcallback
;
2582 ret
->closecallback
= xmlInputCallbackTable
[i
].closecallback
;
2583 #ifdef LIBXML_ZLIB_ENABLED
2584 if ((xmlInputCallbackTable
[i
].opencallback
== xmlGzfileOpen
) &&
2585 (strcmp(URI
, "-") != 0)) {
2586 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
2587 ret
->compressed
= !gzdirect(context
);
2589 if (((z_stream
*)context
)->avail_in
> 4) {
2590 char *cptr
, buff4
[4];
2591 cptr
= (char *) ((z_stream
*)context
)->next_in
;
2592 if (gzread(context
, buff4
, 4) == 4) {
2593 if (strncmp(buff4
, cptr
, 4) == 0)
2594 ret
->compressed
= 0;
2596 ret
->compressed
= 1;
2603 #ifdef LIBXML_LZMA_ENABLED
2604 if ((xmlInputCallbackTable
[i
].opencallback
== xmlXzfileOpen
) &&
2605 (strcmp(URI
, "-") != 0)) {
2606 ret
->compressed
= __libxml2_xzcompressed(context
);
2611 xmlInputCallbackTable
[i
].closecallback (context
);
2617 * xmlParserInputBufferCreateFilename:
2618 * @URI: a C string containing the URI or filename
2619 * @enc: the charset encoding if known
2621 * Create a buffered parser input for the progressive parsing of a file
2622 * If filename is "-' then we use stdin as the input.
2623 * Automatic support for ZLIB/Compress compressed document is provided
2624 * by default if found at compile-time.
2625 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
2627 * Returns the new parser input or NULL
2629 xmlParserInputBufferPtr
2630 xmlParserInputBufferCreateFilename(const char *URI
, xmlCharEncoding enc
) {
2631 if ((xmlParserInputBufferCreateFilenameValue
)) {
2632 return xmlParserInputBufferCreateFilenameValue(URI
, enc
);
2634 return __xmlParserInputBufferCreateFilename(URI
, enc
);
2637 #ifdef LIBXML_OUTPUT_ENABLED
2639 __xmlOutputBufferCreateFilename(const char *URI
,
2640 xmlCharEncodingHandlerPtr encoder
,
2641 int compression ATTRIBUTE_UNUSED
) {
2642 xmlOutputBufferPtr ret
;
2645 void *context
= NULL
;
2646 char *unescaped
= NULL
;
2647 #ifdef LIBXML_ZLIB_ENABLED
2648 int is_file_uri
= 1;
2651 if (xmlOutputCallbackInitialized
== 0)
2652 xmlRegisterDefaultOutputCallbacks();
2654 if (URI
== NULL
) return(NULL
);
2656 puri
= xmlParseURI(URI
);
2658 #ifdef LIBXML_ZLIB_ENABLED
2659 if ((puri
->scheme
!= NULL
) &&
2660 (!xmlStrEqual(BAD_CAST puri
->scheme
, BAD_CAST
"file")))
2664 * try to limit the damages of the URI unescaping code.
2666 if ((puri
->scheme
== NULL
) ||
2667 (xmlStrEqual(BAD_CAST puri
->scheme
, BAD_CAST
"file")))
2668 unescaped
= xmlURIUnescapeString(URI
, 0, NULL
);
2673 * Try to find one of the output accept method accepting that scheme
2674 * Go in reverse to give precedence to user defined handlers.
2675 * try with an unescaped version of the URI
2677 if (unescaped
!= NULL
) {
2678 #ifdef LIBXML_ZLIB_ENABLED
2679 if ((compression
> 0) && (compression
<= 9) && (is_file_uri
== 1)) {
2680 context
= xmlGzfileOpenW(unescaped
, compression
);
2681 if (context
!= NULL
) {
2682 ret
= xmlAllocOutputBufferInternal(encoder
);
2684 ret
->context
= context
;
2685 ret
->writecallback
= xmlGzfileWrite
;
2686 ret
->closecallback
= xmlGzfileClose
;
2693 for (i
= xmlOutputCallbackNr
- 1;i
>= 0;i
--) {
2694 if ((xmlOutputCallbackTable
[i
].matchcallback
!= NULL
) &&
2695 (xmlOutputCallbackTable
[i
].matchcallback(unescaped
) != 0)) {
2696 #if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2697 /* Need to pass compression parameter into HTTP open calls */
2698 if (xmlOutputCallbackTable
[i
].matchcallback
== xmlIOHTTPMatch
)
2699 context
= xmlIOHTTPOpenW(unescaped
, compression
);
2702 context
= xmlOutputCallbackTable
[i
].opencallback(unescaped
);
2703 if (context
!= NULL
)
2711 * If this failed try with a non-escaped URI this may be a strange
2714 if (context
== NULL
) {
2715 #ifdef LIBXML_ZLIB_ENABLED
2716 if ((compression
> 0) && (compression
<= 9) && (is_file_uri
== 1)) {
2717 context
= xmlGzfileOpenW(URI
, compression
);
2718 if (context
!= NULL
) {
2719 ret
= xmlAllocOutputBufferInternal(encoder
);
2721 ret
->context
= context
;
2722 ret
->writecallback
= xmlGzfileWrite
;
2723 ret
->closecallback
= xmlGzfileClose
;
2726 xmlGzfileClose(context
);
2731 for (i
= xmlOutputCallbackNr
- 1;i
>= 0;i
--) {
2732 if ((xmlOutputCallbackTable
[i
].matchcallback
!= NULL
) &&
2733 (xmlOutputCallbackTable
[i
].matchcallback(URI
) != 0)) {
2734 #if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2735 /* Need to pass compression parameter into HTTP open calls */
2736 if (xmlOutputCallbackTable
[i
].matchcallback
== xmlIOHTTPMatch
)
2737 context
= xmlIOHTTPOpenW(URI
, compression
);
2740 context
= xmlOutputCallbackTable
[i
].opencallback(URI
);
2741 if (context
!= NULL
)
2747 if (context
== NULL
) {
2752 * Allocate the Output buffer front-end.
2754 ret
= xmlAllocOutputBufferInternal(encoder
);
2756 ret
->context
= context
;
2757 ret
->writecallback
= xmlOutputCallbackTable
[i
].writecallback
;
2758 ret
->closecallback
= xmlOutputCallbackTable
[i
].closecallback
;
2764 * xmlOutputBufferCreateFilename:
2765 * @URI: a C string containing the URI or filename
2766 * @encoder: the encoding converter or NULL
2767 * @compression: the compression ration (0 none, 9 max).
2769 * Create a buffered output for the progressive saving of a file
2770 * If filename is "-' then we use stdout as the output.
2771 * Automatic support for ZLIB/Compress compressed document is provided
2772 * by default if found at compile-time.
2773 * TODO: currently if compression is set, the library only support
2774 * writing to a local file.
2776 * Returns the new output or NULL
2779 xmlOutputBufferCreateFilename(const char *URI
,
2780 xmlCharEncodingHandlerPtr encoder
,
2781 int compression ATTRIBUTE_UNUSED
) {
2782 if ((xmlOutputBufferCreateFilenameValue
)) {
2783 return xmlOutputBufferCreateFilenameValue(URI
, encoder
, compression
);
2785 return __xmlOutputBufferCreateFilename(URI
, encoder
, compression
);
2787 #endif /* LIBXML_OUTPUT_ENABLED */
2790 * xmlParserInputBufferCreateFile:
2792 * @enc: the charset encoding if known
2794 * Create a buffered parser input for the progressive parsing of a FILE *
2797 * Returns the new parser input or NULL
2799 xmlParserInputBufferPtr
2800 xmlParserInputBufferCreateFile(FILE *file
, xmlCharEncoding enc
) {
2801 xmlParserInputBufferPtr ret
;
2803 if (xmlInputCallbackInitialized
== 0)
2804 xmlRegisterDefaultInputCallbacks();
2806 if (file
== NULL
) return(NULL
);
2808 ret
= xmlAllocParserInputBuffer(enc
);
2810 ret
->context
= file
;
2811 ret
->readcallback
= xmlFileRead
;
2812 ret
->closecallback
= xmlFileFlush
;
2818 #ifdef LIBXML_OUTPUT_ENABLED
2820 * xmlOutputBufferCreateFile:
2822 * @encoder: the encoding converter or NULL
2824 * Create a buffered output for the progressive saving to a FILE *
2827 * Returns the new parser output or NULL
2830 xmlOutputBufferCreateFile(FILE *file
, xmlCharEncodingHandlerPtr encoder
) {
2831 xmlOutputBufferPtr ret
;
2833 if (xmlOutputCallbackInitialized
== 0)
2834 xmlRegisterDefaultOutputCallbacks();
2836 if (file
== NULL
) return(NULL
);
2838 ret
= xmlAllocOutputBufferInternal(encoder
);
2840 ret
->context
= file
;
2841 ret
->writecallback
= xmlFileWrite
;
2842 ret
->closecallback
= xmlFileFlush
;
2849 * xmlOutputBufferCreateBuffer:
2850 * @buffer: a xmlBufferPtr
2851 * @encoder: the encoding converter or NULL
2853 * Create a buffered output for the progressive saving to a xmlBuffer
2855 * Returns the new parser output or NULL
2858 xmlOutputBufferCreateBuffer(xmlBufferPtr buffer
,
2859 xmlCharEncodingHandlerPtr encoder
) {
2860 xmlOutputBufferPtr ret
;
2862 if (buffer
== NULL
) return(NULL
);
2864 ret
= xmlOutputBufferCreateIO(xmlBufferWrite
, NULL
, (void *) buffer
,
2871 * xmlOutputBufferGetContent:
2872 * @out: an xmlOutputBufferPtr
2874 * Gives a pointer to the data currently held in the output buffer
2876 * Returns a pointer to the data or NULL in case of error
2879 xmlOutputBufferGetContent(xmlOutputBufferPtr out
) {
2880 if ((out
== NULL
) || (out
->buffer
== NULL
))
2883 return(xmlBufContent(out
->buffer
));
2887 * xmlOutputBufferGetSize:
2888 * @out: an xmlOutputBufferPtr
2890 * Gives the length of the data currently held in the output buffer
2892 * Returns 0 in case or error or no data is held, the size otherwise
2895 xmlOutputBufferGetSize(xmlOutputBufferPtr out
) {
2896 if ((out
== NULL
) || (out
->buffer
== NULL
))
2899 return(xmlBufUse(out
->buffer
));
2903 #endif /* LIBXML_OUTPUT_ENABLED */
2906 * xmlParserInputBufferCreateFd:
2907 * @fd: a file descriptor number
2908 * @enc: the charset encoding if known
2910 * Create a buffered parser input for the progressive parsing for the input
2911 * from a file descriptor
2913 * Returns the new parser input or NULL
2915 xmlParserInputBufferPtr
2916 xmlParserInputBufferCreateFd(int fd
, xmlCharEncoding enc
) {
2917 xmlParserInputBufferPtr ret
;
2919 if (fd
< 0) return(NULL
);
2921 ret
= xmlAllocParserInputBuffer(enc
);
2923 ret
->context
= (void *) (ptrdiff_t) fd
;
2924 ret
->readcallback
= xmlFdRead
;
2925 ret
->closecallback
= xmlFdClose
;
2932 * xmlParserInputBufferCreateMem:
2933 * @mem: the memory input
2934 * @size: the length of the memory block
2935 * @enc: the charset encoding if known
2937 * Create a buffered parser input for the progressive parsing for the input
2938 * from a memory area.
2940 * Returns the new parser input or NULL
2942 xmlParserInputBufferPtr
2943 xmlParserInputBufferCreateMem(const char *mem
, int size
, xmlCharEncoding enc
) {
2944 xmlParserInputBufferPtr ret
;
2947 if (size
< 0) return(NULL
);
2948 if (mem
== NULL
) return(NULL
);
2950 ret
= xmlAllocParserInputBuffer(enc
);
2952 ret
->context
= (void *) mem
;
2953 ret
->readcallback
= xmlInputReadCallbackNop
;
2954 ret
->closecallback
= NULL
;
2955 errcode
= xmlBufAdd(ret
->buffer
, (const xmlChar
*) mem
, size
);
2966 * xmlParserInputBufferCreateStatic:
2967 * @mem: the memory input
2968 * @size: the length of the memory block
2969 * @enc: the charset encoding if known
2971 * Create a buffered parser input for the progressive parsing for the input
2972 * from an immutable memory area. This will not copy the memory area to
2973 * the buffer, but the memory is expected to be available until the end of
2974 * the parsing, this is useful for example when using mmap'ed file.
2976 * Returns the new parser input or NULL
2978 xmlParserInputBufferPtr
2979 xmlParserInputBufferCreateStatic(const char *mem
, int size
,
2980 xmlCharEncoding enc
) {
2981 xmlParserInputBufferPtr ret
;
2983 if (size
< 0) return(NULL
);
2984 if (mem
== NULL
) return(NULL
);
2986 ret
= (xmlParserInputBufferPtr
) xmlMalloc(sizeof(xmlParserInputBuffer
));
2988 xmlIOErrMemory("creating input buffer");
2991 memset(ret
, 0, (size_t) sizeof(xmlParserInputBuffer
));
2992 ret
->buffer
= xmlBufCreateStatic((void *)mem
, (size_t) size
);
2993 if (ret
->buffer
== NULL
) {
2997 ret
->encoder
= xmlGetCharEncodingHandler(enc
);
2998 if (ret
->encoder
!= NULL
)
2999 ret
->raw
= xmlBufCreateSize(2 * xmlDefaultBufferSize
);
3002 ret
->compressed
= -1;
3003 ret
->context
= (void *) mem
;
3004 ret
->readcallback
= NULL
;
3005 ret
->closecallback
= NULL
;
3010 #ifdef LIBXML_OUTPUT_ENABLED
3012 * xmlOutputBufferCreateFd:
3013 * @fd: a file descriptor number
3014 * @encoder: the encoding converter or NULL
3016 * Create a buffered output for the progressive saving
3017 * to a file descriptor
3019 * Returns the new parser output or NULL
3022 xmlOutputBufferCreateFd(int fd
, xmlCharEncodingHandlerPtr encoder
) {
3023 xmlOutputBufferPtr ret
;
3025 if (fd
< 0) return(NULL
);
3027 ret
= xmlAllocOutputBufferInternal(encoder
);
3029 ret
->context
= (void *) (ptrdiff_t) fd
;
3030 ret
->writecallback
= xmlFdWrite
;
3031 ret
->closecallback
= NULL
;
3036 #endif /* LIBXML_OUTPUT_ENABLED */
3039 * xmlParserInputBufferCreateIO:
3040 * @ioread: an I/O read function
3041 * @ioclose: an I/O close function
3042 * @ioctx: an I/O handler
3043 * @enc: the charset encoding if known
3045 * Create a buffered parser input for the progressive parsing for the input
3046 * from an I/O handler
3048 * Returns the new parser input or NULL
3050 xmlParserInputBufferPtr
3051 xmlParserInputBufferCreateIO(xmlInputReadCallback ioread
,
3052 xmlInputCloseCallback ioclose
, void *ioctx
, xmlCharEncoding enc
) {
3053 xmlParserInputBufferPtr ret
;
3055 if (ioread
== NULL
) return(NULL
);
3057 ret
= xmlAllocParserInputBuffer(enc
);
3059 ret
->context
= (void *) ioctx
;
3060 ret
->readcallback
= ioread
;
3061 ret
->closecallback
= ioclose
;
3067 #ifdef LIBXML_OUTPUT_ENABLED
3069 * xmlOutputBufferCreateIO:
3070 * @iowrite: an I/O write function
3071 * @ioclose: an I/O close function
3072 * @ioctx: an I/O handler
3073 * @encoder: the charset encoding if known
3075 * Create a buffered output for the progressive saving
3078 * Returns the new parser output or NULL
3081 xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite
,
3082 xmlOutputCloseCallback ioclose
, void *ioctx
,
3083 xmlCharEncodingHandlerPtr encoder
) {
3084 xmlOutputBufferPtr ret
;
3086 if (iowrite
== NULL
) return(NULL
);
3088 ret
= xmlAllocOutputBufferInternal(encoder
);
3090 ret
->context
= (void *) ioctx
;
3091 ret
->writecallback
= iowrite
;
3092 ret
->closecallback
= ioclose
;
3097 #endif /* LIBXML_OUTPUT_ENABLED */
3100 * xmlParserInputBufferCreateFilenameDefault:
3101 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
3103 * Registers a callback for URI input file handling
3105 * Returns the old value of the registration function
3107 xmlParserInputBufferCreateFilenameFunc
3108 xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func
)
3110 xmlParserInputBufferCreateFilenameFunc old
= xmlParserInputBufferCreateFilenameValue
;
3112 old
= __xmlParserInputBufferCreateFilename
;
3115 xmlParserInputBufferCreateFilenameValue
= func
;
3120 * xmlOutputBufferCreateFilenameDefault:
3121 * @func: function pointer to the new OutputBufferCreateFilenameFunc
3123 * Registers a callback for URI output file handling
3125 * Returns the old value of the registration function
3127 xmlOutputBufferCreateFilenameFunc
3128 xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func
)
3130 xmlOutputBufferCreateFilenameFunc old
= xmlOutputBufferCreateFilenameValue
;
3131 #ifdef LIBXML_OUTPUT_ENABLED
3133 old
= __xmlOutputBufferCreateFilename
;
3136 xmlOutputBufferCreateFilenameValue
= func
;
3141 * xmlParserInputBufferPush:
3142 * @in: a buffered parser input
3143 * @len: the size in bytes of the array.
3144 * @buf: an char array
3146 * Push the content of the arry in the input buffer
3147 * This routine handle the I18N transcoding to internal UTF-8
3148 * This is used when operating the parser in progressive (push) mode.
3150 * Returns the number of chars read and stored in the buffer, or -1
3154 xmlParserInputBufferPush(xmlParserInputBufferPtr in
,
3155 int len
, const char *buf
) {
3159 if (len
< 0) return(0);
3160 if ((in
== NULL
) || (in
->error
)) return(-1);
3161 if (in
->encoder
!= NULL
) {
3165 * Store the data in the incoming raw buffer
3167 if (in
->raw
== NULL
) {
3168 in
->raw
= xmlBufCreate();
3170 ret
= xmlBufAdd(in
->raw
, (const xmlChar
*) buf
, len
);
3175 * convert as much as possible to the parser reading buffer.
3177 use
= xmlBufUse(in
->raw
);
3178 nbchars
= xmlCharEncInput(in
, 1);
3180 xmlIOErr(XML_IO_ENCODER
, NULL
);
3181 in
->error
= XML_IO_ENCODER
;
3184 in
->rawconsumed
+= (use
- xmlBufUse(in
->raw
));
3187 ret
= xmlBufAdd(in
->buffer
, (xmlChar
*) buf
, nbchars
);
3192 xmlGenericError(xmlGenericErrorContext
,
3193 "I/O: pushed %d chars, buffer %d/%d\n",
3194 nbchars
, xmlBufUse(in
->buffer
), xmlBufLength(in
->buffer
));
3202 * When reading from an Input channel indicated end of file or error
3203 * don't reread from it again.
3206 endOfInput (void * context ATTRIBUTE_UNUSED
,
3207 char * buffer ATTRIBUTE_UNUSED
,
3208 int len ATTRIBUTE_UNUSED
) {
3213 * xmlParserInputBufferGrow:
3214 * @in: a buffered parser input
3215 * @len: indicative value of the amount of chars to read
3217 * Grow up the content of the input buffer, the old data are preserved
3218 * This routine handle the I18N transcoding to internal UTF-8
3219 * This routine is used when operating the parser in normal (pull) mode
3221 * TODO: one should be able to remove one extra copy by copying directly
3222 * onto in->buffer or in->raw
3224 * Returns the number of chars read and stored in the buffer, or -1
3228 xmlParserInputBufferGrow(xmlParserInputBufferPtr in
, int len
) {
3229 char *buffer
= NULL
;
3233 if ((in
== NULL
) || (in
->error
)) return(-1);
3234 if ((len
<= MINLEN
) && (len
!= 4))
3237 if (xmlBufAvail(in
->buffer
) <= 0) {
3238 xmlIOErr(XML_IO_BUFFER_FULL
, NULL
);
3239 in
->error
= XML_IO_BUFFER_FULL
;
3243 if (xmlBufGrow(in
->buffer
, len
+ 1) < 0) {
3244 xmlIOErrMemory("growing input buffer");
3245 in
->error
= XML_ERR_NO_MEMORY
;
3248 buffer
= (char *)xmlBufEnd(in
->buffer
);
3251 * Call the read method for this I/O type.
3253 if (in
->readcallback
!= NULL
) {
3254 res
= in
->readcallback(in
->context
, &buffer
[0], len
);
3256 in
->readcallback
= endOfInput
;
3258 xmlIOErr(XML_IO_NO_INPUT
, NULL
);
3259 in
->error
= XML_IO_NO_INPUT
;
3267 * try to establish compressed status of input if not done already
3269 if (in
->compressed
== -1) {
3270 #ifdef LIBXML_LZMA_ENABLED
3271 if (in
->readcallback
== xmlXzfileRead
)
3272 in
->compressed
= __libxml2_xzcompressed(in
->context
);
3277 if (in
->encoder
!= NULL
) {
3281 * Store the data in the incoming raw buffer
3283 if (in
->raw
== NULL
) {
3284 in
->raw
= xmlBufCreate();
3286 res
= xmlBufAdd(in
->raw
, (const xmlChar
*) buffer
, len
);
3291 * convert as much as possible to the parser reading buffer.
3293 use
= xmlBufUse(in
->raw
);
3294 nbchars
= xmlCharEncInput(in
, 1);
3296 xmlIOErr(XML_IO_ENCODER
, NULL
);
3297 in
->error
= XML_IO_ENCODER
;
3300 in
->rawconsumed
+= (use
- xmlBufUse(in
->raw
));
3303 xmlBufAddLen(in
->buffer
, nbchars
);
3306 xmlGenericError(xmlGenericErrorContext
,
3307 "I/O: read %d chars, buffer %d\n",
3308 nbchars
, xmlBufUse(in
->buffer
));
3314 * xmlParserInputBufferRead:
3315 * @in: a buffered parser input
3316 * @len: indicative value of the amount of chars to read
3318 * Refresh the content of the input buffer, the old data are considered
3320 * This routine handle the I18N transcoding to internal UTF-8
3322 * Returns the number of chars read and stored in the buffer, or -1
3326 xmlParserInputBufferRead(xmlParserInputBufferPtr in
, int len
) {
3327 if ((in
== NULL
) || (in
->error
)) return(-1);
3328 if (in
->readcallback
!= NULL
)
3329 return(xmlParserInputBufferGrow(in
, len
));
3330 else if (xmlBufGetAllocationScheme(in
->buffer
) == XML_BUFFER_ALLOC_IMMUTABLE
)
3336 #ifdef LIBXML_OUTPUT_ENABLED
3338 * xmlOutputBufferWrite:
3339 * @out: a buffered parser output
3340 * @len: the size in bytes of the array.
3341 * @buf: an char array
3343 * Write the content of the array in the output I/O buffer
3344 * This routine handle the I18N transcoding from internal UTF-8
3345 * The buffer is lossless, i.e. will store in case of partial
3346 * or delayed writes.
3348 * Returns the number of chars immediately written, or -1
3352 xmlOutputBufferWrite(xmlOutputBufferPtr out
, int len
, const char *buf
) {
3353 int nbchars
= 0; /* number of chars to output to I/O */
3354 int ret
; /* return from function call */
3355 int written
= 0; /* number of char written to I/O so far */
3356 int chunk
; /* number of byte current processed from buf */
3358 if ((out
== NULL
) || (out
->error
)) return(-1);
3359 if (len
< 0) return(0);
3360 if (out
->error
) return(-1);
3364 if (chunk
> 4 * MINLEN
)
3368 * first handle encoding stuff.
3370 if (out
->encoder
!= NULL
) {
3372 * Store the data in the incoming raw buffer
3374 if (out
->conv
== NULL
) {
3375 out
->conv
= xmlBufCreate();
3377 ret
= xmlBufAdd(out
->buffer
, (const xmlChar
*) buf
, chunk
);
3381 if ((xmlBufUse(out
->buffer
) < MINLEN
) && (chunk
== len
))
3385 * convert as much as possible to the parser reading buffer.
3387 ret
= xmlCharEncOutput(out
, 0);
3388 if ((ret
< 0) && (ret
!= -3)) {
3389 xmlIOErr(XML_IO_ENCODER
, NULL
);
3390 out
->error
= XML_IO_ENCODER
;
3393 if (out
->writecallback
)
3394 nbchars
= xmlBufUse(out
->conv
);
3396 nbchars
= ret
>= 0 ? ret
: 0;
3398 ret
= xmlBufAdd(out
->buffer
, (const xmlChar
*) buf
, chunk
);
3401 if (out
->writecallback
)
3402 nbchars
= xmlBufUse(out
->buffer
);
3409 if (out
->writecallback
) {
3410 if ((nbchars
< MINLEN
) && (len
<= 0))
3414 * second write the stuff to the I/O channel
3416 if (out
->encoder
!= NULL
) {
3417 ret
= out
->writecallback(out
->context
,
3418 (const char *)xmlBufContent(out
->conv
), nbchars
);
3420 xmlBufShrink(out
->conv
, ret
);
3422 ret
= out
->writecallback(out
->context
,
3423 (const char *)xmlBufContent(out
->buffer
), nbchars
);
3425 xmlBufShrink(out
->buffer
, ret
);
3428 xmlIOErr(XML_IO_WRITE
, NULL
);
3429 out
->error
= XML_IO_WRITE
;
3432 if (out
->written
> INT_MAX
- ret
)
3433 out
->written
= INT_MAX
;
3435 out
->written
+= ret
;
3442 xmlGenericError(xmlGenericErrorContext
,
3443 "I/O: wrote %d chars\n", written
);
3450 * @out: a pointer to an array of bytes to store the result
3451 * @outlen: the length of @out
3452 * @in: a pointer to an array of unescaped UTF-8 bytes
3453 * @inlen: the length of @in
3455 * Take a block of UTF-8 chars in and escape them.
3456 * Returns 0 if success, or -1 otherwise
3457 * The value of @inlen after return is the number of octets consumed
3458 * if the return value is positive, else unpredictable.
3459 * The value of @outlen after return is the number of octets consumed.
3462 xmlEscapeContent(unsigned char* out
, int *outlen
,
3463 const xmlChar
* in
, int *inlen
) {
3464 unsigned char* outstart
= out
;
3465 const unsigned char* base
= in
;
3466 unsigned char* outend
= out
+ *outlen
;
3467 const unsigned char* inend
;
3469 inend
= in
+ (*inlen
);
3471 while ((in
< inend
) && (out
< outend
)) {
3473 if (outend
- out
< 4) break;
3478 } else if (*in
== '>') {
3479 if (outend
- out
< 4) break;
3484 } else if (*in
== '&') {
3485 if (outend
- out
< 5) break;
3491 } else if (*in
== '\r') {
3492 if (outend
- out
< 5) break;
3499 *out
++ = (unsigned char) *in
;
3503 *outlen
= out
- outstart
;
3509 * xmlOutputBufferWriteEscape:
3510 * @out: a buffered parser output
3511 * @str: a zero terminated UTF-8 string
3512 * @escaping: an optional escaping function (or NULL)
3514 * Write the content of the string in the output I/O buffer
3515 * This routine escapes the characters and then handle the I18N
3516 * transcoding from internal UTF-8
3517 * The buffer is lossless, i.e. will store in case of partial
3518 * or delayed writes.
3520 * Returns the number of chars immediately written, or -1
3524 xmlOutputBufferWriteEscape(xmlOutputBufferPtr out
, const xmlChar
*str
,
3525 xmlCharEncodingOutputFunc escaping
) {
3526 int nbchars
= 0; /* number of chars to output to I/O */
3527 int ret
; /* return from function call */
3528 int written
= 0; /* number of char written to I/O so far */
3529 int oldwritten
=0;/* loop guard */
3530 int chunk
; /* number of byte currently processed from str */
3531 int len
; /* number of bytes in str */
3532 int cons
; /* byte from str consumed */
3534 if ((out
== NULL
) || (out
->error
) || (str
== NULL
) ||
3535 (out
->buffer
== NULL
) ||
3536 (xmlBufGetAllocationScheme(out
->buffer
) == XML_BUFFER_ALLOC_IMMUTABLE
))
3538 len
= strlen((const char *)str
);
3539 if (len
< 0) return(0);
3540 if (out
->error
) return(-1);
3541 if (escaping
== NULL
) escaping
= xmlEscapeContent
;
3544 oldwritten
= written
;
3547 * how many bytes to consume and how many bytes to store.
3550 chunk
= xmlBufAvail(out
->buffer
);
3553 * make sure we have enough room to save first, if this is
3554 * not the case force a flush, but make sure we stay in the loop
3557 if (xmlBufGrow(out
->buffer
, 100) < 0)
3564 * first handle encoding stuff.
3566 if (out
->encoder
!= NULL
) {
3568 * Store the data in the incoming raw buffer
3570 if (out
->conv
== NULL
) {
3571 out
->conv
= xmlBufCreate();
3573 ret
= escaping(xmlBufEnd(out
->buffer
) ,
3574 &chunk
, str
, &cons
);
3575 if ((ret
< 0) || (chunk
== 0)) /* chunk==0 => nothing done */
3577 xmlBufAddLen(out
->buffer
, chunk
);
3579 if ((xmlBufUse(out
->buffer
) < MINLEN
) && (cons
== len
))
3583 * convert as much as possible to the output buffer.
3585 ret
= xmlCharEncOutput(out
, 0);
3586 if ((ret
< 0) && (ret
!= -3)) {
3587 xmlIOErr(XML_IO_ENCODER
, NULL
);
3588 out
->error
= XML_IO_ENCODER
;
3591 if (out
->writecallback
)
3592 nbchars
= xmlBufUse(out
->conv
);
3594 nbchars
= ret
>= 0 ? ret
: 0;
3596 ret
= escaping(xmlBufEnd(out
->buffer
), &chunk
, str
, &cons
);
3597 if ((ret
< 0) || (chunk
== 0)) /* chunk==0 => nothing done */
3599 xmlBufAddLen(out
->buffer
, chunk
);
3600 if (out
->writecallback
)
3601 nbchars
= xmlBufUse(out
->buffer
);
3608 if (out
->writecallback
) {
3609 if ((nbchars
< MINLEN
) && (len
<= 0))
3613 * second write the stuff to the I/O channel
3615 if (out
->encoder
!= NULL
) {
3616 ret
= out
->writecallback(out
->context
,
3617 (const char *)xmlBufContent(out
->conv
), nbchars
);
3619 xmlBufShrink(out
->conv
, ret
);
3621 ret
= out
->writecallback(out
->context
,
3622 (const char *)xmlBufContent(out
->buffer
), nbchars
);
3624 xmlBufShrink(out
->buffer
, ret
);
3627 xmlIOErr(XML_IO_WRITE
, NULL
);
3628 out
->error
= XML_IO_WRITE
;
3631 if (out
->written
> INT_MAX
- ret
)
3632 out
->written
= INT_MAX
;
3634 out
->written
+= ret
;
3635 } else if (xmlBufAvail(out
->buffer
) < MINLEN
) {
3636 xmlBufGrow(out
->buffer
, MINLEN
);
3639 } while ((len
> 0) && (oldwritten
!= written
));
3643 xmlGenericError(xmlGenericErrorContext
,
3644 "I/O: wrote %d chars\n", written
);
3650 * xmlOutputBufferWriteString:
3651 * @out: a buffered parser output
3652 * @str: a zero terminated C string
3654 * Write the content of the string in the output I/O buffer
3655 * This routine handle the I18N transcoding from internal UTF-8
3656 * The buffer is lossless, i.e. will store in case of partial
3657 * or delayed writes.
3659 * Returns the number of chars immediately written, or -1
3663 xmlOutputBufferWriteString(xmlOutputBufferPtr out
, const char *str
) {
3666 if ((out
== NULL
) || (out
->error
)) return(-1);
3672 return(xmlOutputBufferWrite(out
, len
, str
));
3677 * xmlOutputBufferFlush:
3678 * @out: a buffered output
3680 * flushes the output I/O channel
3682 * Returns the number of byte written or -1 in case of error.
3685 xmlOutputBufferFlush(xmlOutputBufferPtr out
) {
3686 int nbchars
= 0, ret
= 0;
3688 if ((out
== NULL
) || (out
->error
)) return(-1);
3690 * first handle encoding stuff.
3692 if ((out
->conv
!= NULL
) && (out
->encoder
!= NULL
)) {
3694 * convert as much as possible to the parser output buffer.
3697 nbchars
= xmlCharEncOutput(out
, 0);
3699 xmlIOErr(XML_IO_ENCODER
, NULL
);
3700 out
->error
= XML_IO_ENCODER
;
3707 * second flush the stuff to the I/O channel
3709 if ((out
->conv
!= NULL
) && (out
->encoder
!= NULL
) &&
3710 (out
->writecallback
!= NULL
)) {
3711 ret
= out
->writecallback(out
->context
,
3712 (const char *)xmlBufContent(out
->conv
),
3713 xmlBufUse(out
->conv
));
3715 xmlBufShrink(out
->conv
, ret
);
3716 } else if (out
->writecallback
!= NULL
) {
3717 ret
= out
->writecallback(out
->context
,
3718 (const char *)xmlBufContent(out
->buffer
),
3719 xmlBufUse(out
->buffer
));
3721 xmlBufShrink(out
->buffer
, ret
);
3724 xmlIOErr(XML_IO_FLUSH
, NULL
);
3725 out
->error
= XML_IO_FLUSH
;
3728 if (out
->written
> INT_MAX
- ret
)
3729 out
->written
= INT_MAX
;
3731 out
->written
+= ret
;
3734 xmlGenericError(xmlGenericErrorContext
,
3735 "I/O: flushed %d chars\n", ret
);
3739 #endif /* LIBXML_OUTPUT_ENABLED */
3742 * xmlParserGetDirectory:
3743 * @filename: the path to a file
3745 * lookup the directory for that file
3747 * Returns a new allocated string containing the directory, or NULL.
3750 xmlParserGetDirectory(const char *filename
) {
3755 if (xmlInputCallbackInitialized
== 0)
3756 xmlRegisterDefaultInputCallbacks();
3758 if (filename
== NULL
) return(NULL
);
3761 # define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
3763 # define IS_XMLPGD_SEP(ch) (ch=='/')
3766 strncpy(dir
, filename
, 1023);
3768 cur
= &dir
[strlen(dir
)];
3770 if (IS_XMLPGD_SEP(*cur
)) break;
3773 if (IS_XMLPGD_SEP(*cur
)) {
3774 if (cur
== dir
) dir
[1] = 0;
3776 ret
= xmlMemStrdup(dir
);
3778 if (getcwd(dir
, 1024) != NULL
) {
3780 ret
= xmlMemStrdup(dir
);
3784 #undef IS_XMLPGD_SEP
3787 /****************************************************************
3789 * External entities loading *
3791 ****************************************************************/
3794 * xmlCheckHTTPInput:
3795 * @ctxt: an XML parser context
3796 * @ret: an XML parser input
3798 * Check an input in case it was created from an HTTP stream, in that
3799 * case it will handle encoding and update of the base URL in case of
3800 * redirection. It also checks for HTTP errors in which case the input
3801 * is cleanly freed up and an appropriate error is raised in context
3803 * Returns the input or NULL in case of HTTP error.
3806 xmlCheckHTTPInput(xmlParserCtxtPtr ctxt
, xmlParserInputPtr ret
) {
3807 /* Avoid unused variable warning if features are disabled. */
3810 #ifdef LIBXML_HTTP_ENABLED
3811 if ((ret
!= NULL
) && (ret
->buf
!= NULL
) &&
3812 (ret
->buf
->readcallback
== xmlIOHTTPRead
) &&
3813 (ret
->buf
->context
!= NULL
)) {
3814 const char *encoding
;
3819 code
= xmlNanoHTTPReturnCode(ret
->buf
->context
);
3822 if (ret
->filename
!= NULL
)
3823 __xmlLoaderErr(ctxt
, "failed to load HTTP resource \"%s\"\n",
3824 (const char *) ret
->filename
);
3826 __xmlLoaderErr(ctxt
, "failed to load HTTP resource\n", NULL
);
3827 xmlFreeInputStream(ret
);
3831 mime
= xmlNanoHTTPMimeType(ret
->buf
->context
);
3832 if ((xmlStrstr(BAD_CAST mime
, BAD_CAST
"/xml")) ||
3833 (xmlStrstr(BAD_CAST mime
, BAD_CAST
"+xml"))) {
3834 encoding
= xmlNanoHTTPEncoding(ret
->buf
->context
);
3835 if (encoding
!= NULL
) {
3836 xmlCharEncodingHandlerPtr handler
;
3838 handler
= xmlFindCharEncodingHandler(encoding
);
3839 if (handler
!= NULL
) {
3840 xmlSwitchInputEncoding(ctxt
, ret
, handler
);
3842 __xmlErrEncoding(ctxt
, XML_ERR_UNKNOWN_ENCODING
,
3843 "Unknown encoding %s",
3844 BAD_CAST encoding
, NULL
);
3846 if (ret
->encoding
== NULL
)
3847 ret
->encoding
= xmlStrdup(BAD_CAST encoding
);
3850 } else if (xmlStrstr(BAD_CAST mime
, BAD_CAST
"html")) {
3853 redir
= xmlNanoHTTPRedir(ret
->buf
->context
);
3854 if (redir
!= NULL
) {
3855 if (ret
->filename
!= NULL
)
3856 xmlFree((xmlChar
*) ret
->filename
);
3857 if (ret
->directory
!= NULL
) {
3858 xmlFree((xmlChar
*) ret
->directory
);
3859 ret
->directory
= NULL
;
3862 (char *) xmlStrdup((const xmlChar
*) redir
);
3870 static int xmlNoNetExists(const char *URL
) {
3876 if (!xmlStrncasecmp(BAD_CAST URL
, BAD_CAST
"file://localhost/", 17))
3877 #if defined (_WIN32)
3882 else if (!xmlStrncasecmp(BAD_CAST URL
, BAD_CAST
"file:///", 8)) {
3883 #if defined (_WIN32)
3891 return xmlCheckFilename(path
);
3894 #ifdef LIBXML_CATALOG_ENABLED
3897 * xmlResolveResourceFromCatalog:
3898 * @URL: the URL for the entity to load
3899 * @ID: the System ID for the entity to load
3900 * @ctxt: the context in which the entity is called or NULL
3902 * Resolves the URL and ID against the appropriate catalog.
3903 * This function is used by xmlDefaultExternalEntityLoader and
3904 * xmlNoNetExternalEntityLoader.
3906 * Returns a new allocated URL, or NULL.
3909 xmlResolveResourceFromCatalog(const char *URL
, const char *ID
,
3910 xmlParserCtxtPtr ctxt
) {
3911 xmlChar
*resource
= NULL
;
3912 xmlCatalogAllow pref
;
3915 * If the resource doesn't exists as a file,
3916 * try to load it from the resource pointed in the catalogs
3918 pref
= xmlCatalogGetDefaults();
3920 if ((pref
!= XML_CATA_ALLOW_NONE
) && (!xmlNoNetExists(URL
))) {
3924 if ((ctxt
!= NULL
) && (ctxt
->catalogs
!= NULL
) &&
3925 ((pref
== XML_CATA_ALLOW_ALL
) ||
3926 (pref
== XML_CATA_ALLOW_DOCUMENT
))) {
3927 resource
= xmlCatalogLocalResolve(ctxt
->catalogs
,
3928 (const xmlChar
*)ID
,
3929 (const xmlChar
*)URL
);
3932 * Try a global lookup
3934 if ((resource
== NULL
) &&
3935 ((pref
== XML_CATA_ALLOW_ALL
) ||
3936 (pref
== XML_CATA_ALLOW_GLOBAL
))) {
3937 resource
= xmlCatalogResolve((const xmlChar
*)ID
,
3938 (const xmlChar
*)URL
);
3940 if ((resource
== NULL
) && (URL
!= NULL
))
3941 resource
= xmlStrdup((const xmlChar
*) URL
);
3944 * TODO: do an URI lookup on the reference
3946 if ((resource
!= NULL
) && (!xmlNoNetExists((const char *)resource
))) {
3947 xmlChar
*tmp
= NULL
;
3949 if ((ctxt
!= NULL
) && (ctxt
->catalogs
!= NULL
) &&
3950 ((pref
== XML_CATA_ALLOW_ALL
) ||
3951 (pref
== XML_CATA_ALLOW_DOCUMENT
))) {
3952 tmp
= xmlCatalogLocalResolveURI(ctxt
->catalogs
, resource
);
3954 if ((tmp
== NULL
) &&
3955 ((pref
== XML_CATA_ALLOW_ALL
) ||
3956 (pref
== XML_CATA_ALLOW_GLOBAL
))) {
3957 tmp
= xmlCatalogResolveURI(resource
);
3973 * xmlDefaultExternalEntityLoader:
3974 * @URL: the URL for the entity to load
3975 * @ID: the System ID for the entity to load
3976 * @ctxt: the context in which the entity is called or NULL
3978 * By default we don't load external entities, yet.
3980 * Returns a new allocated xmlParserInputPtr, or NULL.
3982 static xmlParserInputPtr
3983 xmlDefaultExternalEntityLoader(const char *URL
, const char *ID
,
3984 xmlParserCtxtPtr ctxt
)
3986 xmlParserInputPtr ret
= NULL
;
3987 xmlChar
*resource
= NULL
;
3989 #ifdef DEBUG_EXTERNAL_ENTITIES
3990 xmlGenericError(xmlGenericErrorContext
,
3991 "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL
);
3993 if ((ctxt
!= NULL
) && (ctxt
->options
& XML_PARSE_NONET
)) {
3994 int options
= ctxt
->options
;
3996 ctxt
->options
-= XML_PARSE_NONET
;
3997 ret
= xmlNoNetExternalEntityLoader(URL
, ID
, ctxt
);
3998 ctxt
->options
= options
;
4001 #ifdef LIBXML_CATALOG_ENABLED
4002 resource
= xmlResolveResourceFromCatalog(URL
, ID
, ctxt
);
4005 if (resource
== NULL
)
4006 resource
= (xmlChar
*) URL
;
4008 if (resource
== NULL
) {
4011 __xmlLoaderErr(ctxt
, "failed to load external entity \"%s\"\n", ID
);
4014 ret
= xmlNewInputFromFile(ctxt
, (const char *) resource
);
4015 if ((resource
!= NULL
) && (resource
!= (xmlChar
*) URL
))
4020 static xmlExternalEntityLoader xmlCurrentExternalEntityLoader
=
4021 xmlDefaultExternalEntityLoader
;
4024 * xmlSetExternalEntityLoader:
4025 * @f: the new entity resolver function
4027 * Changes the defaultexternal entity resolver function for the application
4030 xmlSetExternalEntityLoader(xmlExternalEntityLoader f
) {
4031 xmlCurrentExternalEntityLoader
= f
;
4035 * xmlGetExternalEntityLoader:
4037 * Get the default external entity resolver function for the application
4039 * Returns the xmlExternalEntityLoader function pointer
4041 xmlExternalEntityLoader
4042 xmlGetExternalEntityLoader(void) {
4043 return(xmlCurrentExternalEntityLoader
);
4047 * xmlLoadExternalEntity:
4048 * @URL: the URL for the entity to load
4049 * @ID: the Public ID for the entity to load
4050 * @ctxt: the context in which the entity is called or NULL
4052 * Load an external entity, note that the use of this function for
4053 * unparsed entities may generate problems
4055 * Returns the xmlParserInputPtr or NULL
4058 xmlLoadExternalEntity(const char *URL
, const char *ID
,
4059 xmlParserCtxtPtr ctxt
) {
4060 if ((URL
!= NULL
) && (xmlNoNetExists(URL
) == 0)) {
4061 char *canonicFilename
;
4062 xmlParserInputPtr ret
;
4064 canonicFilename
= (char *) xmlCanonicPath((const xmlChar
*) URL
);
4065 if (canonicFilename
== NULL
) {
4066 xmlIOErrMemory("building canonical path\n");
4070 ret
= xmlCurrentExternalEntityLoader(canonicFilename
, ID
, ctxt
);
4071 xmlFree(canonicFilename
);
4074 return(xmlCurrentExternalEntityLoader(URL
, ID
, ctxt
));
4077 /************************************************************************
4079 * Disabling Network access *
4081 ************************************************************************/
4084 * xmlNoNetExternalEntityLoader:
4085 * @URL: the URL for the entity to load
4086 * @ID: the System ID for the entity to load
4087 * @ctxt: the context in which the entity is called or NULL
4089 * A specific entity loader disabling network accesses, though still
4090 * allowing local catalog accesses for resolution.
4092 * Returns a new allocated xmlParserInputPtr, or NULL.
4095 xmlNoNetExternalEntityLoader(const char *URL
, const char *ID
,
4096 xmlParserCtxtPtr ctxt
) {
4097 xmlParserInputPtr input
= NULL
;
4098 xmlChar
*resource
= NULL
;
4100 #ifdef LIBXML_CATALOG_ENABLED
4101 resource
= xmlResolveResourceFromCatalog(URL
, ID
, ctxt
);
4104 if (resource
== NULL
)
4105 resource
= (xmlChar
*) URL
;
4107 if (resource
!= NULL
) {
4108 if ((!xmlStrncasecmp(BAD_CAST resource
, BAD_CAST
"ftp://", 6)) ||
4109 (!xmlStrncasecmp(BAD_CAST resource
, BAD_CAST
"http://", 7))) {
4110 xmlIOErr(XML_IO_NETWORK_ATTEMPT
, (const char *) resource
);
4111 if (resource
!= (xmlChar
*) URL
)
4116 input
= xmlDefaultExternalEntityLoader((const char *) resource
, ID
, ctxt
);
4117 if (resource
!= (xmlChar
*) URL
)