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
21 #ifdef HAVE_SYS_TYPES_H
22 #include <sys/types.h>
24 #ifdef HAVE_SYS_STAT_H
36 #ifdef LIBXML_ZLIB_ENABLED
39 #ifdef LIBXML_LZMA_ENABLED
43 #if defined(_WIN32) && !defined(__CYGWIN__)
46 #else /* __REACTOS__ */
47 #define WIN32_LEAN_AND_MEAN
49 #endif /* __REACTOS__ */
52 #if defined(_WIN32_WCE)
53 #include <winnls.h> /* for CP_UTF8 */
58 # define S_ISDIR(x) _S_ISDIR(x)
59 # elif defined(S_IFDIR)
61 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
62 # elif defined(_S_IFMT)
63 # define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
68 #include <libxml/xmlmemory.h>
69 #include <libxml/parser.h>
70 #include <libxml/parserInternals.h>
71 #include <libxml/xmlIO.h>
72 #include <libxml/uri.h>
73 #include <libxml/nanohttp.h>
74 #include <libxml/nanoftp.h>
75 #include <libxml/xmlerror.h>
76 #ifdef LIBXML_CATALOG_ENABLED
77 #include <libxml/catalog.h>
79 #include <libxml/globals.h>
84 /* #define VERBOSE_FAILURE */
85 /* #define DEBUG_EXTERNAL_ENTITIES */
86 /* #define DEBUG_INPUT */
95 * Input I/O callback sets
97 typedef struct _xmlInputCallback
{
98 xmlInputMatchCallback matchcallback
;
99 xmlInputOpenCallback opencallback
;
100 xmlInputReadCallback readcallback
;
101 xmlInputCloseCallback closecallback
;
104 #define MAX_INPUT_CALLBACK 15
106 static xmlInputCallback xmlInputCallbackTable
[MAX_INPUT_CALLBACK
];
107 static int xmlInputCallbackNr
= 0;
108 static int xmlInputCallbackInitialized
= 0;
110 #ifdef LIBXML_OUTPUT_ENABLED
112 * Output I/O callback sets
114 typedef struct _xmlOutputCallback
{
115 xmlOutputMatchCallback matchcallback
;
116 xmlOutputOpenCallback opencallback
;
117 xmlOutputWriteCallback writecallback
;
118 xmlOutputCloseCallback closecallback
;
121 #define MAX_OUTPUT_CALLBACK 15
123 static xmlOutputCallback xmlOutputCallbackTable
[MAX_OUTPUT_CALLBACK
];
124 static int xmlOutputCallbackNr
= 0;
125 static int xmlOutputCallbackInitialized
= 0;
128 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder
);
129 #endif /* LIBXML_OUTPUT_ENABLED */
131 /************************************************************************
133 * Tree memory error handler *
135 ************************************************************************/
137 static const char *IOerr
[] = {
138 "Unknown IO error", /* UNKNOWN */
139 "Permission denied", /* EACCES */
140 "Resource temporarily unavailable",/* EAGAIN */
141 "Bad file descriptor", /* EBADF */
142 "Bad message", /* EBADMSG */
143 "Resource busy", /* EBUSY */
144 "Operation canceled", /* ECANCELED */
145 "No child processes", /* ECHILD */
146 "Resource deadlock avoided",/* EDEADLK */
147 "Domain error", /* EDOM */
148 "File exists", /* EEXIST */
149 "Bad address", /* EFAULT */
150 "File too large", /* EFBIG */
151 "Operation in progress", /* EINPROGRESS */
152 "Interrupted function call",/* EINTR */
153 "Invalid argument", /* EINVAL */
154 "Input/output error", /* EIO */
155 "Is a directory", /* EISDIR */
156 "Too many open files", /* EMFILE */
157 "Too many links", /* EMLINK */
158 "Inappropriate message buffer length",/* EMSGSIZE */
159 "Filename too long", /* ENAMETOOLONG */
160 "Too many open files in system",/* ENFILE */
161 "No such device", /* ENODEV */
162 "No such file or directory",/* ENOENT */
163 "Exec format error", /* ENOEXEC */
164 "No locks available", /* ENOLCK */
165 "Not enough space", /* ENOMEM */
166 "No space left on device", /* ENOSPC */
167 "Function not implemented", /* ENOSYS */
168 "Not a directory", /* ENOTDIR */
169 "Directory not empty", /* ENOTEMPTY */
170 "Not supported", /* ENOTSUP */
171 "Inappropriate I/O control operation",/* ENOTTY */
172 "No such device or address",/* ENXIO */
173 "Operation not permitted", /* EPERM */
174 "Broken pipe", /* EPIPE */
175 "Result too large", /* ERANGE */
176 "Read-only file system", /* EROFS */
177 "Invalid seek", /* ESPIPE */
178 "No such process", /* ESRCH */
179 "Operation timed out", /* ETIMEDOUT */
180 "Improper link", /* EXDEV */
181 "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
182 "encoder error", /* XML_IO_ENCODER */
188 "not a socket", /* ENOTSOCK */
189 "already connected", /* EISCONN */
190 "connection refused", /* ECONNREFUSED */
191 "unreachable network", /* ENETUNREACH */
192 "adddress in use", /* EADDRINUSE */
193 "already in use", /* EALREADY */
194 "unknown address familly", /* EAFNOSUPPORT */
197 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
199 * __xmlIOWin32UTF8ToWChar:
200 * @u8String: uft-8 string
202 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
205 __xmlIOWin32UTF8ToWChar(const char *u8String
)
207 wchar_t *wString
= NULL
;
211 MultiByteToWideChar(CP_UTF8
, MB_ERR_INVALID_CHARS
, u8String
,
214 wString
= xmlMalloc(wLen
* sizeof(wchar_t));
216 if (MultiByteToWideChar
217 (CP_UTF8
, 0, u8String
, -1, wString
, wLen
) == 0) {
231 * @extra: extra informations
233 * Handle an out of memory condition
236 xmlIOErrMemory(const char *extra
)
238 __xmlSimpleError(XML_FROM_IO
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
243 * @code: the error number
245 * @extra: extra informations
247 * Handle an I/O error
250 __xmlIOErr(int domain
, int code
, const char *extra
)
256 if (errno
== 0) code
= 0;
258 else if (errno
== EACCES
) code
= XML_IO_EACCES
;
261 else if (errno
== EAGAIN
) code
= XML_IO_EAGAIN
;
264 else if (errno
== EBADF
) code
= XML_IO_EBADF
;
267 else if (errno
== EBADMSG
) code
= XML_IO_EBADMSG
;
270 else if (errno
== EBUSY
) code
= XML_IO_EBUSY
;
273 else if (errno
== ECANCELED
) code
= XML_IO_ECANCELED
;
276 else if (errno
== ECHILD
) code
= XML_IO_ECHILD
;
279 else if (errno
== EDEADLK
) code
= XML_IO_EDEADLK
;
282 else if (errno
== EDOM
) code
= XML_IO_EDOM
;
285 else if (errno
== EEXIST
) code
= XML_IO_EEXIST
;
288 else if (errno
== EFAULT
) code
= XML_IO_EFAULT
;
291 else if (errno
== EFBIG
) code
= XML_IO_EFBIG
;
294 else if (errno
== EINPROGRESS
) code
= XML_IO_EINPROGRESS
;
297 else if (errno
== EINTR
) code
= XML_IO_EINTR
;
300 else if (errno
== EINVAL
) code
= XML_IO_EINVAL
;
303 else if (errno
== EIO
) code
= XML_IO_EIO
;
306 else if (errno
== EISDIR
) code
= XML_IO_EISDIR
;
309 else if (errno
== EMFILE
) code
= XML_IO_EMFILE
;
312 else if (errno
== EMLINK
) code
= XML_IO_EMLINK
;
315 else if (errno
== EMSGSIZE
) code
= XML_IO_EMSGSIZE
;
318 else if (errno
== ENAMETOOLONG
) code
= XML_IO_ENAMETOOLONG
;
321 else if (errno
== ENFILE
) code
= XML_IO_ENFILE
;
324 else if (errno
== ENODEV
) code
= XML_IO_ENODEV
;
327 else if (errno
== ENOENT
) code
= XML_IO_ENOENT
;
330 else if (errno
== ENOEXEC
) code
= XML_IO_ENOEXEC
;
333 else if (errno
== ENOLCK
) code
= XML_IO_ENOLCK
;
336 else if (errno
== ENOMEM
) code
= XML_IO_ENOMEM
;
339 else if (errno
== ENOSPC
) code
= XML_IO_ENOSPC
;
342 else if (errno
== ENOSYS
) code
= XML_IO_ENOSYS
;
345 else if (errno
== ENOTDIR
) code
= XML_IO_ENOTDIR
;
348 else if (errno
== ENOTEMPTY
) code
= XML_IO_ENOTEMPTY
;
351 else if (errno
== ENOTSUP
) code
= XML_IO_ENOTSUP
;
354 else if (errno
== ENOTTY
) code
= XML_IO_ENOTTY
;
357 else if (errno
== ENXIO
) code
= XML_IO_ENXIO
;
360 else if (errno
== EPERM
) code
= XML_IO_EPERM
;
363 else if (errno
== EPIPE
) code
= XML_IO_EPIPE
;
366 else if (errno
== ERANGE
) code
= XML_IO_ERANGE
;
369 else if (errno
== EROFS
) code
= XML_IO_EROFS
;
372 else if (errno
== ESPIPE
) code
= XML_IO_ESPIPE
;
375 else if (errno
== ESRCH
) code
= XML_IO_ESRCH
;
378 else if (errno
== ETIMEDOUT
) code
= XML_IO_ETIMEDOUT
;
381 else if (errno
== EXDEV
) code
= XML_IO_EXDEV
;
384 else if (errno
== ENOTSOCK
) code
= XML_IO_ENOTSOCK
;
387 else if (errno
== EISCONN
) code
= XML_IO_EISCONN
;
390 else if (errno
== ECONNREFUSED
) code
= XML_IO_ECONNREFUSED
;
393 else if (errno
== ETIMEDOUT
) code
= XML_IO_ETIMEDOUT
;
396 else if (errno
== ENETUNREACH
) code
= XML_IO_ENETUNREACH
;
399 else if (errno
== EADDRINUSE
) code
= XML_IO_EADDRINUSE
;
402 else if (errno
== EINPROGRESS
) code
= XML_IO_EINPROGRESS
;
405 else if (errno
== EALREADY
) code
= XML_IO_EALREADY
;
408 else if (errno
== EAFNOSUPPORT
) code
= XML_IO_EAFNOSUPPORT
;
410 else code
= XML_IO_UNKNOWN
;
411 #endif /* HAVE_ERRNO_H */
414 if (code
>= XML_IO_UNKNOWN
) idx
= code
- XML_IO_UNKNOWN
;
415 if (idx
>= (sizeof(IOerr
) / sizeof(IOerr
[0]))) idx
= 0;
417 __xmlSimpleError(domain
, code
, NULL
, IOerr
[idx
], extra
);
422 * @code: the error number
423 * @extra: extra informations
425 * Handle an I/O error
428 xmlIOErr(int code
, const char *extra
)
430 __xmlIOErr(XML_FROM_IO
, code
, extra
);
435 * @ctx: the parser context
436 * @extra: extra informations
438 * Handle a resource access error
441 __xmlLoaderErr(void *ctx
, const char *msg
, const char *filename
)
443 xmlParserCtxtPtr ctxt
= (xmlParserCtxtPtr
) ctx
;
444 xmlStructuredErrorFunc schannel
= NULL
;
445 xmlGenericErrorFunc channel
= NULL
;
447 xmlErrorLevel level
= XML_ERR_ERROR
;
449 if ((ctxt
!= NULL
) && (ctxt
->disableSAX
!= 0) &&
450 (ctxt
->instate
== XML_PARSER_EOF
))
452 if ((ctxt
!= NULL
) && (ctxt
->sax
!= NULL
)) {
453 if (ctxt
->validate
) {
454 channel
= ctxt
->sax
->error
;
455 level
= XML_ERR_ERROR
;
457 channel
= ctxt
->sax
->warning
;
458 level
= XML_ERR_WARNING
;
460 if (ctxt
->sax
->initialized
== XML_SAX2_MAGIC
)
461 schannel
= ctxt
->sax
->serror
;
462 data
= ctxt
->userData
;
464 __xmlRaiseError(schannel
, channel
, data
, ctxt
, NULL
, XML_FROM_IO
,
465 XML_IO_LOAD_ERROR
, level
, NULL
, 0,
466 filename
, NULL
, NULL
, 0, 0,
471 /************************************************************************
473 * Tree memory error handler *
475 ************************************************************************/
477 * xmlNormalizeWindowsPath:
478 * @path: the input file path
480 * This function is obsolete. Please see xmlURIFromPath in uri.c for
483 * Returns a canonicalized version of the path
486 xmlNormalizeWindowsPath(const xmlChar
*path
)
488 return xmlCanonicPath(path
);
492 * xmlCleanupInputCallbacks:
494 * clears the entire input callback table. this includes the
498 xmlCleanupInputCallbacks(void)
502 if (!xmlInputCallbackInitialized
)
505 for (i
= xmlInputCallbackNr
- 1; i
>= 0; i
--) {
506 xmlInputCallbackTable
[i
].matchcallback
= NULL
;
507 xmlInputCallbackTable
[i
].opencallback
= NULL
;
508 xmlInputCallbackTable
[i
].readcallback
= NULL
;
509 xmlInputCallbackTable
[i
].closecallback
= NULL
;
512 xmlInputCallbackNr
= 0;
513 xmlInputCallbackInitialized
= 0;
517 * xmlPopInputCallbacks:
519 * Clear the top input callback from the input stack. this includes the
522 * Returns the number of input callback registered or -1 in case of error.
525 xmlPopInputCallbacks(void)
527 if (!xmlInputCallbackInitialized
)
530 if (xmlInputCallbackNr
<= 0)
533 xmlInputCallbackNr
--;
534 xmlInputCallbackTable
[xmlInputCallbackNr
].matchcallback
= NULL
;
535 xmlInputCallbackTable
[xmlInputCallbackNr
].opencallback
= NULL
;
536 xmlInputCallbackTable
[xmlInputCallbackNr
].readcallback
= NULL
;
537 xmlInputCallbackTable
[xmlInputCallbackNr
].closecallback
= NULL
;
539 return(xmlInputCallbackNr
);
542 #ifdef LIBXML_OUTPUT_ENABLED
544 * xmlCleanupOutputCallbacks:
546 * clears the entire output callback table. this includes the
547 * compiled-in I/O callbacks.
550 xmlCleanupOutputCallbacks(void)
554 if (!xmlOutputCallbackInitialized
)
557 for (i
= xmlOutputCallbackNr
- 1; i
>= 0; i
--) {
558 xmlOutputCallbackTable
[i
].matchcallback
= NULL
;
559 xmlOutputCallbackTable
[i
].opencallback
= NULL
;
560 xmlOutputCallbackTable
[i
].writecallback
= NULL
;
561 xmlOutputCallbackTable
[i
].closecallback
= NULL
;
564 xmlOutputCallbackNr
= 0;
565 xmlOutputCallbackInitialized
= 0;
567 #endif /* LIBXML_OUTPUT_ENABLED */
569 /************************************************************************
571 * Standard I/O for file accesses *
573 ************************************************************************/
575 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
579 * @path: the path in utf-8 encoding
580 * @mode: type of access (0 - read, 1 - write)
582 * function opens the file specified by @path
586 xmlWrapOpenUtf8(const char *path
,int mode
)
591 wPath
= __xmlIOWin32UTF8ToWChar(path
);
594 fd
= _wfopen(wPath
, mode
? L
"wb" : L
"rb");
597 /* maybe path in native encoding */
599 fd
= fopen(path
, mode
? "wb" : "rb");
604 #ifdef LIBXML_ZLIB_ENABLED
606 xmlWrapGzOpenUtf8(const char *path
, const char *mode
)
611 fd
= gzopen (path
, mode
);
615 wPath
= __xmlIOWin32UTF8ToWChar(path
);
618 int d
, m
= (strstr(mode
, "r") ? O_RDONLY
: O_RDWR
);
620 m
|= (strstr(mode
, "b") ? _O_BINARY
: 0);
622 d
= _wopen(wPath
, m
);
624 fd
= gzdopen(d
, mode
);
634 * @path: the path in utf-8 encoding
635 * @info: structure that stores results
637 * function obtains information about the file or directory
641 xmlWrapStatUtf8(const char *path
, struct _stat
*info
) {
645 wPath
= __xmlIOWin32UTF8ToWChar(path
);
647 retval
= _wstat(wPath
, info
);
650 /* maybe path in native encoding */
652 retval
= _stat(path
, info
);
660 * @path: the path to check
662 * function checks to see if @path is a valid source
663 * (file, socket...) for XML.
665 * if stat is not available on the target machine,
666 * returns 1. if stat fails, returns 0 (if calling
667 * stat on the filename fails, it can't be right).
668 * if stat succeeds and the file is a directory,
669 * returns 2. otherwise returns 1.
673 xmlCheckFilename (const char *path
)
676 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
677 struct _stat stat_buffer
;
679 struct stat stat_buffer
;
686 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
688 * On Windows stat and wstat do not work with long pathname,
689 * which start with '\\?\'
691 if ((path
[0] == '\\') && (path
[1] == '\\') && (path
[2] == '?') &&
695 if (xmlWrapStatUtf8(path
, &stat_buffer
) == -1)
698 if (stat(path
, &stat_buffer
) == -1)
702 if (S_ISDIR(stat_buffer
.st_mode
))
705 #endif /* HAVE_STAT */
710 * xmlInputReadCallbackNop:
712 * No Operation xmlInputReadCallback function, does nothing.
717 xmlInputReadCallbackNop(void *context ATTRIBUTE_UNUSED
,
718 char *buffer ATTRIBUTE_UNUSED
,
719 int len ATTRIBUTE_UNUSED
) {
725 * @context: the I/O context
726 * @buffer: where to drop data
727 * @len: number of bytes to read
729 * Read @len bytes to @buffer from the I/O channel.
731 * Returns the number of bytes written
734 xmlFdRead (void * context
, char * buffer
, int len
) {
737 ret
= read((int) (ptrdiff_t) context
, &buffer
[0], len
);
738 if (ret
< 0) xmlIOErr(0, "read()");
742 #ifdef LIBXML_OUTPUT_ENABLED
745 * @context: the I/O context
746 * @buffer: where to get data
747 * @len: number of bytes to write
749 * Write @len bytes from @buffer to the I/O channel.
751 * Returns the number of bytes written
754 xmlFdWrite (void * context
, const char * buffer
, int len
) {
758 ret
= write((int) (ptrdiff_t) context
, &buffer
[0], len
);
759 if (ret
< 0) xmlIOErr(0, "write()");
763 #endif /* LIBXML_OUTPUT_ENABLED */
767 * @context: the I/O context
769 * Close an I/O channel
771 * Returns 0 in case of success and error code otherwise
774 xmlFdClose (void * context
) {
776 ret
= close((int) (ptrdiff_t) context
);
777 if (ret
< 0) xmlIOErr(0, "close()");
783 * @filename: the URI for matching
787 * Returns 1 if matches, 0 otherwise
790 xmlFileMatch (const char *filename ATTRIBUTE_UNUSED
) {
796 * @filename: the URI for matching
798 * input from FILE *, supports compressed input
799 * if @filename is " " then the standard input is used
801 * Returns an I/O context or NULL in case of error
804 xmlFileOpen_real (const char *filename
) {
805 const char *path
= filename
;
808 if (filename
== NULL
)
811 if (!strcmp(filename
, "-")) {
816 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17)) {
817 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
818 path
= &filename
[17];
820 path
= &filename
[16];
822 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
823 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
828 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:/", 6)) {
829 /* lots of generators seems to lazy to read RFC 1738 */
830 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
837 /* Do not check DDNAME on zOS ! */
838 #if !defined(__MVS__)
839 if (!xmlCheckFilename(path
))
843 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
844 fd
= xmlWrapOpenUtf8(path
, 0);
846 fd
= fopen(path
, "r");
848 if (fd
== NULL
) xmlIOErr(0, path
);
854 * @filename: the URI for matching
856 * Wrapper around xmlFileOpen_real that try it with an unescaped
857 * version of @filename, if this fails fallback to @filename
859 * Returns a handler or NULL in case or failure
862 xmlFileOpen (const char *filename
) {
866 retval
= xmlFileOpen_real(filename
);
867 if (retval
== NULL
) {
868 unescaped
= xmlURIUnescapeString(filename
, 0, NULL
);
869 if (unescaped
!= NULL
) {
870 retval
= xmlFileOpen_real(unescaped
);
878 #ifdef LIBXML_OUTPUT_ENABLED
881 * @filename: the URI for matching
883 * output to from FILE *,
884 * if @filename is "-" then the standard output is used
886 * Returns an I/O context or NULL in case of error
889 xmlFileOpenW (const char *filename
) {
890 const char *path
= NULL
;
893 if (!strcmp(filename
, "-")) {
898 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17))
899 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
900 path
= &filename
[17];
902 path
= &filename
[16];
904 else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
905 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
916 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
917 fd
= xmlWrapOpenUtf8(path
, 1);
919 fd
= fopen(path
, "w");
921 fd
= fopen(path
, "wb");
924 if (fd
== NULL
) xmlIOErr(0, path
);
927 #endif /* LIBXML_OUTPUT_ENABLED */
931 * @context: the I/O context
932 * @buffer: where to drop data
933 * @len: number of bytes to write
935 * Read @len bytes to @buffer from the I/O channel.
937 * Returns the number of bytes written or < 0 in case of failure
940 xmlFileRead (void * context
, char * buffer
, int len
) {
942 if ((context
== NULL
) || (buffer
== NULL
))
944 ret
= fread(&buffer
[0], 1, len
, (FILE *) context
);
945 if (ret
< 0) xmlIOErr(0, "fread()");
949 #ifdef LIBXML_OUTPUT_ENABLED
952 * @context: the I/O context
953 * @buffer: where to drop data
954 * @len: number of bytes to write
956 * Write @len bytes from @buffer to the I/O channel.
958 * Returns the number of bytes written
961 xmlFileWrite (void * context
, const char * buffer
, int len
) {
964 if ((context
== NULL
) || (buffer
== NULL
))
966 items
= fwrite(&buffer
[0], len
, 1, (FILE *) context
);
967 if ((items
== 0) && (ferror((FILE *) context
))) {
968 xmlIOErr(0, "fwrite()");
973 #endif /* LIBXML_OUTPUT_ENABLED */
977 * @context: the I/O context
979 * Close an I/O channel
981 * Returns 0 or -1 in case of error
984 xmlFileClose (void * context
) {
990 fil
= (FILE *) context
;
991 if ((fil
== stdout
) || (fil
== stderr
)) {
994 xmlIOErr(0, "fflush()");
999 ret
= ( fclose((FILE *) context
) == EOF
) ? -1 : 0;
1001 xmlIOErr(0, "fclose()");
1007 * @context: the I/O context
1009 * Flush an I/O channel
1012 xmlFileFlush (void * context
) {
1015 if (context
== NULL
)
1017 ret
= ( fflush((FILE *) context
) == EOF
) ? -1 : 0;
1019 xmlIOErr(0, "fflush()");
1023 #ifdef LIBXML_OUTPUT_ENABLED
1026 * @context: the xmlBuffer
1027 * @buffer: the data to write
1028 * @len: number of bytes to write
1030 * Write @len bytes from @buffer to the xml buffer
1032 * Returns the number of bytes written
1035 xmlBufferWrite (void * context
, const char * buffer
, int len
) {
1038 ret
= xmlBufferAdd((xmlBufferPtr
) context
, (const xmlChar
*) buffer
, len
);
1045 #ifdef LIBXML_ZLIB_ENABLED
1046 /************************************************************************
1048 * I/O for compressed file accesses *
1050 ************************************************************************/
1053 * @filename: the URI for matching
1055 * input from compressed file test
1057 * Returns 1 if matches, 0 otherwise
1060 xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED
) {
1065 * xmlGzfileOpen_real:
1066 * @filename: the URI for matching
1068 * input from compressed file open
1069 * if @filename is " " then the standard input is used
1071 * Returns an I/O context or NULL in case of error
1074 xmlGzfileOpen_real (const char *filename
) {
1075 const char *path
= NULL
;
1078 if (!strcmp(filename
, "-")) {
1079 int duped_fd
= dup(fileno(stdin
));
1080 fd
= gzdopen(duped_fd
, "rb");
1081 if (fd
== Z_NULL
&& duped_fd
>= 0) {
1082 close(duped_fd
); /* gzdOpen() does not close on failure */
1085 return((void *) fd
);
1088 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17))
1089 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1090 path
= &filename
[17];
1092 path
= &filename
[16];
1094 else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
1095 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1096 path
= &filename
[8];
1098 path
= &filename
[7];
1105 if (!xmlCheckFilename(path
))
1108 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1109 fd
= xmlWrapGzOpenUtf8(path
, "rb");
1111 fd
= gzopen(path
, "rb");
1113 return((void *) fd
);
1118 * @filename: the URI for matching
1120 * Wrapper around xmlGzfileOpen if the open fais, it will
1121 * try to unescape @filename
1124 xmlGzfileOpen (const char *filename
) {
1128 retval
= xmlGzfileOpen_real(filename
);
1129 if (retval
== NULL
) {
1130 unescaped
= xmlURIUnescapeString(filename
, 0, NULL
);
1131 if (unescaped
!= NULL
) {
1132 retval
= xmlGzfileOpen_real(unescaped
);
1139 #ifdef LIBXML_OUTPUT_ENABLED
1142 * @filename: the URI for matching
1143 * @compression: the compression factor (0 - 9 included)
1145 * input from compressed file open
1146 * if @filename is " " then the standard input is used
1148 * Returns an I/O context or NULL in case of error
1151 xmlGzfileOpenW (const char *filename
, int compression
) {
1152 const char *path
= NULL
;
1156 snprintf(mode
, sizeof(mode
), "wb%d", compression
);
1157 if (!strcmp(filename
, "-")) {
1158 int duped_fd
= dup(fileno(stdout
));
1159 fd
= gzdopen(duped_fd
, "rb");
1160 if (fd
== Z_NULL
&& duped_fd
>= 0) {
1161 close(duped_fd
); /* gzdOpen() does not close on failure */
1164 return((void *) fd
);
1167 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17))
1168 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1169 path
= &filename
[17];
1171 path
= &filename
[16];
1173 else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
1174 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1175 path
= &filename
[8];
1177 path
= &filename
[7];
1185 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1186 fd
= xmlWrapGzOpenUtf8(path
, mode
);
1188 fd
= gzopen(path
, mode
);
1190 return((void *) fd
);
1192 #endif /* LIBXML_OUTPUT_ENABLED */
1196 * @context: the I/O context
1197 * @buffer: where to drop data
1198 * @len: number of bytes to write
1200 * Read @len bytes to @buffer from the compressed I/O channel.
1202 * Returns the number of bytes read.
1205 xmlGzfileRead (void * context
, char * buffer
, int len
) {
1208 ret
= gzread((gzFile
) context
, &buffer
[0], len
);
1209 if (ret
< 0) xmlIOErr(0, "gzread()");
1213 #ifdef LIBXML_OUTPUT_ENABLED
1216 * @context: the I/O context
1217 * @buffer: where to drop data
1218 * @len: number of bytes to write
1220 * Write @len bytes from @buffer to the compressed I/O channel.
1222 * Returns the number of bytes written
1225 xmlGzfileWrite (void * context
, const char * buffer
, int len
) {
1228 ret
= gzwrite((gzFile
) context
, (char *) &buffer
[0], len
);
1229 if (ret
< 0) xmlIOErr(0, "gzwrite()");
1232 #endif /* LIBXML_OUTPUT_ENABLED */
1236 * @context: the I/O context
1238 * Close a compressed I/O channel
1241 xmlGzfileClose (void * context
) {
1244 ret
= (gzclose((gzFile
) context
) == Z_OK
) ? 0 : -1;
1245 if (ret
< 0) xmlIOErr(0, "gzclose()");
1248 #endif /* LIBXML_ZLIB_ENABLED */
1250 #ifdef LIBXML_LZMA_ENABLED
1251 /************************************************************************
1253 * I/O for compressed file accesses *
1255 ************************************************************************/
1259 * @filename: the URI for matching
1261 * input from compressed file test
1263 * Returns 1 if matches, 0 otherwise
1266 xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED
) {
1271 * xmlXzFileOpen_real:
1272 * @filename: the URI for matching
1274 * input from compressed file open
1275 * if @filename is " " then the standard input is used
1277 * Returns an I/O context or NULL in case of error
1280 xmlXzfileOpen_real (const char *filename
) {
1281 const char *path
= NULL
;
1284 if (!strcmp(filename
, "-")) {
1285 fd
= __libxml2_xzdopen(dup(fileno(stdin
)), "rb");
1286 return((void *) fd
);
1289 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file://localhost/", 17)) {
1290 path
= &filename
[16];
1291 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:///", 8)) {
1292 path
= &filename
[7];
1293 } else if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"file:/", 6)) {
1294 /* lots of generators seems to lazy to read RFC 1738 */
1295 path
= &filename
[5];
1301 if (!xmlCheckFilename(path
))
1304 fd
= __libxml2_xzopen(path
, "rb");
1305 return((void *) fd
);
1310 * @filename: the URI for matching
1312 * Wrapper around xmlXzfileOpen_real that try it with an unescaped
1313 * version of @filename, if this fails fallback to @filename
1315 * Returns a handler or NULL in case or failure
1318 xmlXzfileOpen (const char *filename
) {
1322 retval
= xmlXzfileOpen_real(filename
);
1323 if (retval
== NULL
) {
1324 unescaped
= xmlURIUnescapeString(filename
, 0, NULL
);
1325 if (unescaped
!= NULL
) {
1326 retval
= xmlXzfileOpen_real(unescaped
);
1336 * @context: the I/O context
1337 * @buffer: where to drop data
1338 * @len: number of bytes to write
1340 * Read @len bytes to @buffer from the compressed I/O channel.
1342 * Returns the number of bytes written
1345 xmlXzfileRead (void * context
, char * buffer
, int len
) {
1348 ret
= __libxml2_xzread((xzFile
) context
, &buffer
[0], len
);
1349 if (ret
< 0) xmlIOErr(0, "xzread()");
1355 * @context: the I/O context
1357 * Close a compressed I/O channel
1360 xmlXzfileClose (void * context
) {
1363 ret
= (__libxml2_xzclose((xzFile
) context
) == LZMA_OK
) ? 0 : -1;
1364 if (ret
< 0) xmlIOErr(0, "xzclose()");
1367 #endif /* LIBXML_LZMA_ENABLED */
1369 #ifdef LIBXML_HTTP_ENABLED
1370 /************************************************************************
1372 * I/O for HTTP file accesses *
1374 ************************************************************************/
1376 #ifdef LIBXML_OUTPUT_ENABLED
1377 typedef struct xmlIOHTTPWriteCtxt_
1385 } xmlIOHTTPWriteCtxt
, *xmlIOHTTPWriteCtxtPtr
;
1387 #ifdef LIBXML_ZLIB_ENABLED
1389 #define DFLT_WBITS ( -15 )
1390 #define DFLT_MEM_LVL ( 8 )
1391 #define GZ_MAGIC1 ( 0x1f )
1392 #define GZ_MAGIC2 ( 0x8b )
1393 #define LXML_ZLIB_OS_CODE ( 0x03 )
1394 #define INIT_HTTP_BUFF_SIZE ( 32768 )
1395 #define DFLT_ZLIB_RATIO ( 5 )
1398 ** Data structure and functions to work with sending compressed data
1402 typedef struct xmlZMemBuff_
1407 unsigned char * zbuff
;
1410 } xmlZMemBuff
, *xmlZMemBuffPtr
;
1413 * append_reverse_ulong
1414 * @buff: Compressed memory buffer
1415 * @data: Unsigned long to append
1417 * Append a unsigned long in reverse byte order to the end of the
1421 append_reverse_ulong( xmlZMemBuff
* buff
, unsigned long data
) {
1429 ** This is plagiarized from putLong in gzio.c (zlib source) where
1430 ** the number "4" is hardcoded. If zlib is ever patched to
1431 ** support 64 bit file sizes, this code would need to be patched
1435 for ( idx
= 0; idx
< 4; idx
++ ) {
1436 *buff
->zctrl
.next_out
= ( data
& 0xff );
1438 buff
->zctrl
.next_out
++;
1447 * @buff: The memory buffer context to clear
1449 * Release all the resources associated with the compressed memory buffer.
1452 xmlFreeZMemBuff( xmlZMemBuffPtr buff
) {
1461 xmlFree( buff
->zbuff
);
1463 z_err
= deflateEnd( &buff
->zctrl
);
1464 if ( z_err
!= Z_OK
)
1465 xmlGenericError( xmlGenericErrorContext
,
1466 "xmlFreeZMemBuff: Error releasing zlib context: %d\n",
1469 deflateEnd( &buff
->zctrl
);
1478 *@compression: Compression value to use
1480 * Create a memory buffer to hold the compressed XML document. The
1481 * compressed document in memory will end up being identical to what
1482 * would be created if gzopen/gzwrite/gzclose were being used to
1483 * write the document to disk. The code for the header/trailer data to
1484 * the compression is plagiarized from the zlib source files.
1487 xmlCreateZMemBuff( int compression
) {
1491 xmlZMemBuffPtr buff
= NULL
;
1493 if ( ( compression
< 1 ) || ( compression
> 9 ) )
1496 /* Create the control and data areas */
1498 buff
= xmlMalloc( sizeof( xmlZMemBuff
) );
1499 if ( buff
== NULL
) {
1500 xmlIOErrMemory("creating buffer context");
1504 (void)memset( buff
, 0, sizeof( xmlZMemBuff
) );
1505 buff
->size
= INIT_HTTP_BUFF_SIZE
;
1506 buff
->zbuff
= xmlMalloc( buff
->size
);
1507 if ( buff
->zbuff
== NULL
) {
1508 xmlFreeZMemBuff( buff
);
1509 xmlIOErrMemory("creating buffer");
1513 z_err
= deflateInit2( &buff
->zctrl
, compression
, Z_DEFLATED
,
1514 DFLT_WBITS
, DFLT_MEM_LVL
, Z_DEFAULT_STRATEGY
);
1515 if ( z_err
!= Z_OK
) {
1517 xmlFreeZMemBuff( buff
);
1519 xmlStrPrintf(msg
, 500,
1520 "xmlCreateZMemBuff: %s %d\n",
1521 "Error initializing compression context. ZLIB error:",
1523 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1527 /* Set the header data. The CRC will be needed for the trailer */
1528 buff
->crc
= crc32( 0L, NULL
, 0 );
1529 hdr_lgth
= snprintf( (char *)buff
->zbuff
, buff
->size
,
1530 "%c%c%c%c%c%c%c%c%c%c",
1531 GZ_MAGIC1
, GZ_MAGIC2
, Z_DEFLATED
,
1532 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE
);
1533 buff
->zctrl
.next_out
= buff
->zbuff
+ hdr_lgth
;
1534 buff
->zctrl
.avail_out
= buff
->size
- hdr_lgth
;
1541 * @buff: Buffer used to compress and consolidate data.
1542 * @ext_amt: Number of bytes to extend the buffer.
1544 * Extend the internal buffer used to store the compressed data by the
1547 * Returns 0 on success or -1 on failure to extend the buffer. On failure
1548 * the original buffer still exists at the original size.
1551 xmlZMemBuffExtend( xmlZMemBuffPtr buff
, size_t ext_amt
) {
1557 unsigned char * tmp_ptr
= NULL
;
1562 else if ( ext_amt
== 0 )
1565 cur_used
= buff
->zctrl
.next_out
- buff
->zbuff
;
1566 new_size
= buff
->size
+ ext_amt
;
1569 if ( cur_used
> new_size
)
1570 xmlGenericError( xmlGenericErrorContext
,
1571 "xmlZMemBuffExtend: %s\n%s %d bytes.\n",
1572 "Buffer overwrite detected during compressed memory",
1573 "buffer extension. Overflowed by",
1574 (cur_used
- new_size
) );
1577 tmp_ptr
= xmlRealloc( buff
->zbuff
, new_size
);
1578 if ( tmp_ptr
!= NULL
) {
1580 buff
->size
= new_size
;
1581 buff
->zbuff
= tmp_ptr
;
1582 buff
->zctrl
.next_out
= tmp_ptr
+ cur_used
;
1583 buff
->zctrl
.avail_out
= new_size
- cur_used
;
1587 xmlStrPrintf(msg
, 500,
1588 "xmlZMemBuffExtend: %s %lu bytes.\n",
1589 "Allocation failure extending output buffer to",
1590 (unsigned long) new_size
);
1591 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1599 * @buff: Buffer used to compress and consolidate data
1600 * @src: Uncompressed source content to append to buffer
1601 * @len: Length of source data to append to buffer
1603 * Compress and append data to the internal buffer. The data buffer
1604 * will be expanded if needed to store the additional data.
1606 * Returns the number of bytes appended to the buffer or -1 on error.
1609 xmlZMemBuffAppend( xmlZMemBuffPtr buff
, const char * src
, int len
) {
1614 if ( ( buff
== NULL
) || ( src
== NULL
) )
1617 buff
->zctrl
.avail_in
= len
;
1618 buff
->zctrl
.next_in
= (unsigned char *)src
;
1619 while ( buff
->zctrl
.avail_in
> 0 ) {
1621 ** Extend the buffer prior to deflate call if a reasonable amount
1622 ** of output buffer space is not available.
1624 min_accept
= buff
->zctrl
.avail_in
/ DFLT_ZLIB_RATIO
;
1625 if ( buff
->zctrl
.avail_out
<= min_accept
) {
1626 if ( xmlZMemBuffExtend( buff
, buff
->size
) == -1 )
1630 z_err
= deflate( &buff
->zctrl
, Z_NO_FLUSH
);
1631 if ( z_err
!= Z_OK
) {
1633 xmlStrPrintf(msg
, 500,
1634 "xmlZMemBuffAppend: %s %d %s - %d",
1635 "Compression error while appending",
1636 len
, "bytes to buffer. ZLIB error", z_err
);
1637 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1642 buff
->crc
= crc32( buff
->crc
, (unsigned char *)src
, len
);
1648 * xmlZMemBuffGetContent
1649 * @buff: Compressed memory content buffer
1650 * @data_ref: Pointer reference to point to compressed content
1652 * Flushes the compression buffers, appends gzip file trailers and
1653 * returns the compressed content and length of the compressed data.
1654 * NOTE: The gzip trailer code here is plagiarized from zlib source.
1656 * Returns the length of the compressed data or -1 on error.
1659 xmlZMemBuffGetContent( xmlZMemBuffPtr buff
, char ** data_ref
) {
1664 if ( ( buff
== NULL
) || ( data_ref
== NULL
) )
1667 /* Need to loop until compression output buffers are flushed */
1671 z_err
= deflate( &buff
->zctrl
, Z_FINISH
);
1672 if ( z_err
== Z_OK
) {
1673 /* In this case Z_OK means more buffer space needed */
1675 if ( xmlZMemBuffExtend( buff
, buff
->size
) == -1 )
1679 while ( z_err
== Z_OK
);
1681 /* If the compression state is not Z_STREAM_END, some error occurred */
1683 if ( z_err
== Z_STREAM_END
) {
1685 /* Need to append the gzip data trailer */
1687 if ( buff
->zctrl
.avail_out
< ( 2 * sizeof( unsigned long ) ) ) {
1688 if ( xmlZMemBuffExtend(buff
, (2 * sizeof(unsigned long))) == -1 )
1693 ** For whatever reason, the CRC and length data are pushed out
1694 ** in reverse byte order. So a memcpy can't be used here.
1697 append_reverse_ulong( buff
, buff
->crc
);
1698 append_reverse_ulong( buff
, buff
->zctrl
.total_in
);
1700 zlgth
= buff
->zctrl
.next_out
- buff
->zbuff
;
1701 *data_ref
= (char *)buff
->zbuff
;
1706 xmlStrPrintf(msg
, 500,
1707 "xmlZMemBuffGetContent: %s - %d\n",
1708 "Error flushing zlib buffers. Error code", z_err
);
1709 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1714 #endif /* LIBXML_OUTPUT_ENABLED */
1715 #endif /* LIBXML_ZLIB_ENABLED */
1717 #ifdef LIBXML_OUTPUT_ENABLED
1719 * xmlFreeHTTPWriteCtxt
1720 * @ctxt: Context to cleanup
1722 * Free allocated memory and reclaim system resources.
1727 xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt
)
1729 if ( ctxt
->uri
!= NULL
)
1730 xmlFree( ctxt
->uri
);
1732 if ( ctxt
->doc_buff
!= NULL
) {
1734 #ifdef LIBXML_ZLIB_ENABLED
1735 if ( ctxt
->compression
> 0 ) {
1736 xmlFreeZMemBuff( ctxt
->doc_buff
);
1741 xmlOutputBufferClose( ctxt
->doc_buff
);
1748 #endif /* LIBXML_OUTPUT_ENABLED */
1753 * @filename: the URI for matching
1755 * check if the URI matches an HTTP one
1757 * Returns 1 if matches, 0 otherwise
1760 xmlIOHTTPMatch (const char *filename
) {
1761 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"http://", 7))
1768 * @filename: the URI for matching
1770 * open an HTTP I/O channel
1772 * Returns an I/O context or NULL in case of error
1775 xmlIOHTTPOpen (const char *filename
) {
1776 return(xmlNanoHTTPOpen(filename
, NULL
));
1779 #ifdef LIBXML_OUTPUT_ENABLED
1782 * @post_uri: The destination URI for the document
1783 * @compression: The compression desired for the document.
1785 * Open a temporary buffer to collect the document for a subsequent HTTP POST
1786 * request. Non-static as is called from the output buffer creation routine.
1788 * Returns an I/O context or NULL in case of error.
1792 xmlIOHTTPOpenW(const char *post_uri
, int compression ATTRIBUTE_UNUSED
)
1795 xmlIOHTTPWriteCtxtPtr ctxt
= NULL
;
1797 if (post_uri
== NULL
)
1800 ctxt
= xmlMalloc(sizeof(xmlIOHTTPWriteCtxt
));
1802 xmlIOErrMemory("creating HTTP output context");
1806 (void) memset(ctxt
, 0, sizeof(xmlIOHTTPWriteCtxt
));
1808 ctxt
->uri
= (char *) xmlStrdup((const xmlChar
*)post_uri
);
1809 if (ctxt
->uri
== NULL
) {
1810 xmlIOErrMemory("copying URI");
1811 xmlFreeHTTPWriteCtxt(ctxt
);
1816 * ** Since the document length is required for an HTTP post,
1817 * ** need to put the document into a buffer. A memory buffer
1818 * ** is being used to avoid pushing the data to disk and back.
1821 #ifdef LIBXML_ZLIB_ENABLED
1822 if ((compression
> 0) && (compression
<= 9)) {
1824 ctxt
->compression
= compression
;
1825 ctxt
->doc_buff
= xmlCreateZMemBuff(compression
);
1829 /* Any character conversions should have been done before this */
1831 ctxt
->doc_buff
= xmlAllocOutputBufferInternal(NULL
);
1834 if (ctxt
->doc_buff
== NULL
) {
1835 xmlFreeHTTPWriteCtxt(ctxt
);
1841 #endif /* LIBXML_OUTPUT_ENABLED */
1843 #ifdef LIBXML_OUTPUT_ENABLED
1845 * xmlIOHTTPDfltOpenW
1846 * @post_uri: The destination URI for this document.
1848 * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
1849 * HTTP post command. This function should generally not be used as
1850 * the open callback is short circuited in xmlOutputBufferCreateFile.
1852 * Returns a pointer to the new IO context.
1855 xmlIOHTTPDfltOpenW( const char * post_uri
) {
1856 return ( xmlIOHTTPOpenW( post_uri
, 0 ) );
1858 #endif /* LIBXML_OUTPUT_ENABLED */
1862 * @context: the I/O context
1863 * @buffer: where to drop data
1864 * @len: number of bytes to write
1866 * Read @len bytes to @buffer from the I/O channel.
1868 * Returns the number of bytes written
1871 xmlIOHTTPRead(void * context
, char * buffer
, int len
) {
1872 if ((buffer
== NULL
) || (len
< 0)) return(-1);
1873 return(xmlNanoHTTPRead(context
, &buffer
[0], len
));
1876 #ifdef LIBXML_OUTPUT_ENABLED
1879 * @context: previously opened writing context
1880 * @buffer: data to output to temporary buffer
1881 * @len: bytes to output
1883 * Collect data from memory buffer into a temporary file for later
1886 * Returns number of bytes written.
1890 xmlIOHTTPWrite( void * context
, const char * buffer
, int len
) {
1892 xmlIOHTTPWriteCtxtPtr ctxt
= context
;
1894 if ( ( ctxt
== NULL
) || ( ctxt
->doc_buff
== NULL
) || ( buffer
== NULL
) )
1899 /* Use gzwrite or fwrite as previously setup in the open call */
1901 #ifdef LIBXML_ZLIB_ENABLED
1902 if ( ctxt
->compression
> 0 )
1903 len
= xmlZMemBuffAppend( ctxt
->doc_buff
, buffer
, len
);
1907 len
= xmlOutputBufferWrite( ctxt
->doc_buff
, len
, buffer
);
1911 xmlStrPrintf(msg
, 500,
1912 "xmlIOHTTPWrite: %s\n%s '%s'.\n",
1913 "Error appending to internal buffer.",
1914 "Error sending document to URI",
1916 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1922 #endif /* LIBXML_OUTPUT_ENABLED */
1927 * @context: the I/O context
1929 * Close an HTTP I/O channel
1934 xmlIOHTTPClose (void * context
) {
1935 xmlNanoHTTPClose(context
);
1939 #ifdef LIBXML_OUTPUT_ENABLED
1941 * xmlIOHTTCloseWrite
1942 * @context: The I/O context
1943 * @http_mthd: The HTTP method to be used when sending the data
1945 * Close the transmit HTTP I/O channel and actually send the data.
1948 xmlIOHTTPCloseWrite( void * context
, const char * http_mthd
) {
1952 int content_lgth
= 0;
1953 xmlIOHTTPWriteCtxtPtr ctxt
= context
;
1955 char * http_content
= NULL
;
1956 char * content_encoding
= NULL
;
1957 char * content_type
= (char *) "text/xml";
1958 void * http_ctxt
= NULL
;
1960 if ( ( ctxt
== NULL
) || ( http_mthd
== NULL
) )
1963 /* Retrieve the content from the appropriate buffer */
1965 #ifdef LIBXML_ZLIB_ENABLED
1967 if ( ctxt
->compression
> 0 ) {
1968 content_lgth
= xmlZMemBuffGetContent( ctxt
->doc_buff
, &http_content
);
1969 content_encoding
= (char *) "Content-Encoding: gzip";
1974 /* Pull the data out of the memory output buffer */
1976 xmlOutputBufferPtr dctxt
= ctxt
->doc_buff
;
1977 http_content
= (char *) xmlBufContent(dctxt
->buffer
);
1978 content_lgth
= xmlBufUse(dctxt
->buffer
);
1981 if ( http_content
== NULL
) {
1983 xmlStrPrintf(msg
, 500,
1984 "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
1985 "Error retrieving content.\nUnable to",
1986 http_mthd
, "data to URI", ctxt
->uri
);
1987 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
1992 http_ctxt
= xmlNanoHTTPMethod( ctxt
->uri
, http_mthd
, http_content
,
1993 &content_type
, content_encoding
,
1996 if ( http_ctxt
!= NULL
) {
1998 /* If testing/debugging - dump reply with request content */
2000 FILE * tst_file
= NULL
;
2001 char buffer
[ 4096 ];
2002 char * dump_name
= NULL
;
2005 xmlGenericError( xmlGenericErrorContext
,
2006 "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n",
2007 http_mthd
, ctxt
->uri
,
2008 xmlNanoHTTPReturnCode( http_ctxt
) );
2011 ** Since either content or reply may be gzipped,
2012 ** dump them to separate files instead of the
2013 ** standard error context.
2016 dump_name
= tempnam( NULL
, "lxml" );
2017 if ( dump_name
!= NULL
) {
2018 (void)snprintf( buffer
, sizeof(buffer
), "%s.content", dump_name
);
2020 tst_file
= fopen( buffer
, "wb" );
2021 if ( tst_file
!= NULL
) {
2022 xmlGenericError( xmlGenericErrorContext
,
2023 "Transmitted content saved in file: %s\n", buffer
);
2025 fwrite( http_content
, sizeof( char ),
2026 content_lgth
, tst_file
);
2030 (void)snprintf( buffer
, sizeof(buffer
), "%s.reply", dump_name
);
2031 tst_file
= fopen( buffer
, "wb" );
2032 if ( tst_file
!= NULL
) {
2033 xmlGenericError( xmlGenericErrorContext
,
2034 "Reply content saved in file: %s\n", buffer
);
2037 while ( (avail
= xmlNanoHTTPRead( http_ctxt
,
2038 buffer
, sizeof( buffer
) )) > 0 ) {
2040 fwrite( buffer
, sizeof( char ), avail
, tst_file
);
2048 #endif /* DEBUG_HTTP */
2050 http_rtn
= xmlNanoHTTPReturnCode( http_ctxt
);
2051 if ( ( http_rtn
>= 200 ) && ( http_rtn
< 300 ) )
2055 xmlStrPrintf(msg
, 500,
2056 "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
2057 http_mthd
, content_lgth
,
2058 "bytes to URI", ctxt
->uri
,
2059 "failed. HTTP return code:", http_rtn
);
2060 xmlIOErr(XML_IO_WRITE
, (const char *) msg
);
2063 xmlNanoHTTPClose( http_ctxt
);
2064 xmlFree( content_type
);
2068 /* Final cleanups */
2070 xmlFreeHTTPWriteCtxt( ctxt
);
2072 return ( close_rc
);
2078 * @context: The I/O context
2080 * Close the transmit HTTP I/O channel and actually send data using a PUT
2084 xmlIOHTTPClosePut( void * ctxt
) {
2085 return ( xmlIOHTTPCloseWrite( ctxt
, "PUT" ) );
2090 * xmlIOHTTPClosePost
2092 * @context: The I/O context
2094 * Close the transmit HTTP I/O channel and actually send data using a POST
2098 xmlIOHTTPClosePost( void * ctxt
) {
2099 return ( xmlIOHTTPCloseWrite( ctxt
, "POST" ) );
2101 #endif /* LIBXML_OUTPUT_ENABLED */
2103 #endif /* LIBXML_HTTP_ENABLED */
2105 #ifdef LIBXML_FTP_ENABLED
2106 /************************************************************************
2108 * I/O for FTP file accesses *
2110 ************************************************************************/
2113 * @filename: the URI for matching
2115 * check if the URI matches an FTP one
2117 * Returns 1 if matches, 0 otherwise
2120 xmlIOFTPMatch (const char *filename
) {
2121 if (!xmlStrncasecmp(BAD_CAST filename
, BAD_CAST
"ftp://", 6))
2128 * @filename: the URI for matching
2130 * open an FTP I/O channel
2132 * Returns an I/O context or NULL in case of error
2135 xmlIOFTPOpen (const char *filename
) {
2136 return(xmlNanoFTPOpen(filename
));
2141 * @context: the I/O context
2142 * @buffer: where to drop data
2143 * @len: number of bytes to write
2145 * Read @len bytes to @buffer from the I/O channel.
2147 * Returns the number of bytes written
2150 xmlIOFTPRead(void * context
, char * buffer
, int len
) {
2151 if ((buffer
== NULL
) || (len
< 0)) return(-1);
2152 return(xmlNanoFTPRead(context
, &buffer
[0], len
));
2157 * @context: the I/O context
2159 * Close an FTP I/O channel
2164 xmlIOFTPClose (void * context
) {
2165 return ( xmlNanoFTPClose(context
) );
2167 #endif /* LIBXML_FTP_ENABLED */
2171 * xmlRegisterInputCallbacks:
2172 * @matchFunc: the xmlInputMatchCallback
2173 * @openFunc: the xmlInputOpenCallback
2174 * @readFunc: the xmlInputReadCallback
2175 * @closeFunc: the xmlInputCloseCallback
2177 * Register a new set of I/O callback for handling parser input.
2179 * Returns the registered handler number or -1 in case of error
2182 xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc
,
2183 xmlInputOpenCallback openFunc
, xmlInputReadCallback readFunc
,
2184 xmlInputCloseCallback closeFunc
) {
2185 if (xmlInputCallbackNr
>= MAX_INPUT_CALLBACK
) {
2188 xmlInputCallbackTable
[xmlInputCallbackNr
].matchcallback
= matchFunc
;
2189 xmlInputCallbackTable
[xmlInputCallbackNr
].opencallback
= openFunc
;
2190 xmlInputCallbackTable
[xmlInputCallbackNr
].readcallback
= readFunc
;
2191 xmlInputCallbackTable
[xmlInputCallbackNr
].closecallback
= closeFunc
;
2192 xmlInputCallbackInitialized
= 1;
2193 return(xmlInputCallbackNr
++);
2196 #ifdef LIBXML_OUTPUT_ENABLED
2198 * xmlRegisterOutputCallbacks:
2199 * @matchFunc: the xmlOutputMatchCallback
2200 * @openFunc: the xmlOutputOpenCallback
2201 * @writeFunc: the xmlOutputWriteCallback
2202 * @closeFunc: the xmlOutputCloseCallback
2204 * Register a new set of I/O callback for handling output.
2206 * Returns the registered handler number or -1 in case of error
2209 xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc
,
2210 xmlOutputOpenCallback openFunc
, xmlOutputWriteCallback writeFunc
,
2211 xmlOutputCloseCallback closeFunc
) {
2212 if (xmlOutputCallbackNr
>= MAX_OUTPUT_CALLBACK
) {
2215 xmlOutputCallbackTable
[xmlOutputCallbackNr
].matchcallback
= matchFunc
;
2216 xmlOutputCallbackTable
[xmlOutputCallbackNr
].opencallback
= openFunc
;
2217 xmlOutputCallbackTable
[xmlOutputCallbackNr
].writecallback
= writeFunc
;
2218 xmlOutputCallbackTable
[xmlOutputCallbackNr
].closecallback
= closeFunc
;
2219 xmlOutputCallbackInitialized
= 1;
2220 return(xmlOutputCallbackNr
++);
2222 #endif /* LIBXML_OUTPUT_ENABLED */
2225 * xmlRegisterDefaultInputCallbacks:
2227 * Registers the default compiled-in I/O handlers.
2230 xmlRegisterDefaultInputCallbacks(void) {
2231 if (xmlInputCallbackInitialized
)
2234 xmlRegisterInputCallbacks(xmlFileMatch
, xmlFileOpen
,
2235 xmlFileRead
, xmlFileClose
);
2236 #ifdef LIBXML_ZLIB_ENABLED
2237 xmlRegisterInputCallbacks(xmlGzfileMatch
, xmlGzfileOpen
,
2238 xmlGzfileRead
, xmlGzfileClose
);
2239 #endif /* LIBXML_ZLIB_ENABLED */
2240 #ifdef LIBXML_LZMA_ENABLED
2241 xmlRegisterInputCallbacks(xmlXzfileMatch
, xmlXzfileOpen
,
2242 xmlXzfileRead
, xmlXzfileClose
);
2243 #endif /* LIBXML_LZMA_ENABLED */
2245 #ifdef LIBXML_HTTP_ENABLED
2246 xmlRegisterInputCallbacks(xmlIOHTTPMatch
, xmlIOHTTPOpen
,
2247 xmlIOHTTPRead
, xmlIOHTTPClose
);
2248 #endif /* LIBXML_HTTP_ENABLED */
2250 #ifdef LIBXML_FTP_ENABLED
2251 xmlRegisterInputCallbacks(xmlIOFTPMatch
, xmlIOFTPOpen
,
2252 xmlIOFTPRead
, xmlIOFTPClose
);
2253 #endif /* LIBXML_FTP_ENABLED */
2254 xmlInputCallbackInitialized
= 1;
2257 #ifdef LIBXML_OUTPUT_ENABLED
2259 * xmlRegisterDefaultOutputCallbacks:
2261 * Registers the default compiled-in I/O handlers.
2264 xmlRegisterDefaultOutputCallbacks (void) {
2265 if (xmlOutputCallbackInitialized
)
2268 xmlRegisterOutputCallbacks(xmlFileMatch
, xmlFileOpenW
,
2269 xmlFileWrite
, xmlFileClose
);
2271 #ifdef LIBXML_HTTP_ENABLED
2272 xmlRegisterOutputCallbacks(xmlIOHTTPMatch
, xmlIOHTTPDfltOpenW
,
2273 xmlIOHTTPWrite
, xmlIOHTTPClosePut
);
2276 /*********************************
2277 No way a-priori to distinguish between gzipped files from
2278 uncompressed ones except opening if existing then closing
2279 and saving with same compression ratio ... a pain.
2281 #ifdef LIBXML_ZLIB_ENABLED
2282 xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2283 xmlGzfileWrite, xmlGzfileClose);
2287 #ifdef LIBXML_FTP_ENABLED
2288 xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2289 xmlIOFTPWrite, xmlIOFTPClose);
2291 **********************************/
2292 xmlOutputCallbackInitialized
= 1;
2295 #ifdef LIBXML_HTTP_ENABLED
2297 * xmlRegisterHTTPPostCallbacks:
2299 * By default, libxml submits HTTP output requests using the "PUT" method.
2300 * Calling this method changes the HTTP output method to use the "POST"
2305 xmlRegisterHTTPPostCallbacks( void ) {
2307 /* Register defaults if not done previously */
2309 if ( xmlOutputCallbackInitialized
== 0 )
2310 xmlRegisterDefaultOutputCallbacks( );
2312 xmlRegisterOutputCallbacks(xmlIOHTTPMatch
, xmlIOHTTPDfltOpenW
,
2313 xmlIOHTTPWrite
, xmlIOHTTPClosePost
);
2317 #endif /* LIBXML_OUTPUT_ENABLED */
2320 * xmlAllocParserInputBuffer:
2321 * @enc: the charset encoding if known
2323 * Create a buffered parser input for progressive parsing
2325 * Returns the new parser input or NULL
2327 xmlParserInputBufferPtr
2328 xmlAllocParserInputBuffer(xmlCharEncoding enc
) {
2329 xmlParserInputBufferPtr ret
;
2331 ret
= (xmlParserInputBufferPtr
) xmlMalloc(sizeof(xmlParserInputBuffer
));
2333 xmlIOErrMemory("creating input buffer");
2336 memset(ret
, 0, (size_t) sizeof(xmlParserInputBuffer
));
2337 ret
->buffer
= xmlBufCreateSize(2 * xmlDefaultBufferSize
);
2338 if (ret
->buffer
== NULL
) {
2342 xmlBufSetAllocationScheme(ret
->buffer
, XML_BUFFER_ALLOC_DOUBLEIT
);
2343 ret
->encoder
= xmlGetCharEncodingHandler(enc
);
2344 if (ret
->encoder
!= NULL
)
2345 ret
->raw
= xmlBufCreateSize(2 * xmlDefaultBufferSize
);
2348 ret
->readcallback
= NULL
;
2349 ret
->closecallback
= NULL
;
2350 ret
->context
= NULL
;
2351 ret
->compressed
= -1;
2352 ret
->rawconsumed
= 0;
2357 #ifdef LIBXML_OUTPUT_ENABLED
2359 * xmlAllocOutputBuffer:
2360 * @encoder: the encoding converter or NULL
2362 * Create a buffered parser output
2364 * Returns the new parser output or NULL
2367 xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder
) {
2368 xmlOutputBufferPtr ret
;
2370 ret
= (xmlOutputBufferPtr
) xmlMalloc(sizeof(xmlOutputBuffer
));
2372 xmlIOErrMemory("creating output buffer");
2375 memset(ret
, 0, (size_t) sizeof(xmlOutputBuffer
));
2376 ret
->buffer
= xmlBufCreate();
2377 if (ret
->buffer
== NULL
) {
2382 /* try to avoid a performance problem with Windows realloc() */
2383 if (xmlBufGetAllocationScheme(ret
->buffer
) == XML_BUFFER_ALLOC_EXACT
)
2384 xmlBufSetAllocationScheme(ret
->buffer
, XML_BUFFER_ALLOC_DOUBLEIT
);
2386 ret
->encoder
= encoder
;
2387 if (encoder
!= NULL
) {
2388 ret
->conv
= xmlBufCreateSize(4000);
2389 if (ret
->conv
== NULL
) {
2395 * This call is designed to initiate the encoder state
2397 xmlCharEncOutput(ret
, 1);
2400 ret
->writecallback
= NULL
;
2401 ret
->closecallback
= NULL
;
2402 ret
->context
= NULL
;
2409 * xmlAllocOutputBufferInternal:
2410 * @encoder: the encoding converter or NULL
2412 * Create a buffered parser output
2414 * Returns the new parser output or NULL
2417 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder
) {
2418 xmlOutputBufferPtr ret
;
2420 ret
= (xmlOutputBufferPtr
) xmlMalloc(sizeof(xmlOutputBuffer
));
2422 xmlIOErrMemory("creating output buffer");
2425 memset(ret
, 0, (size_t) sizeof(xmlOutputBuffer
));
2426 ret
->buffer
= xmlBufCreate();
2427 if (ret
->buffer
== NULL
) {
2434 * For conversion buffers we use the special IO handling
2436 xmlBufSetAllocationScheme(ret
->buffer
, XML_BUFFER_ALLOC_IO
);
2438 ret
->encoder
= encoder
;
2439 if (encoder
!= NULL
) {
2440 ret
->conv
= xmlBufCreateSize(4000);
2441 if (ret
->conv
== NULL
) {
2447 * This call is designed to initiate the encoder state
2449 xmlCharEncOutput(ret
, 1);
2452 ret
->writecallback
= NULL
;
2453 ret
->closecallback
= NULL
;
2454 ret
->context
= NULL
;
2460 #endif /* LIBXML_OUTPUT_ENABLED */
2463 * xmlFreeParserInputBuffer:
2464 * @in: a buffered parser input
2466 * Free up the memory used by a buffered parser input
2469 xmlFreeParserInputBuffer(xmlParserInputBufferPtr in
) {
2470 if (in
== NULL
) return;
2473 xmlBufFree(in
->raw
);
2476 if (in
->encoder
!= NULL
) {
2477 xmlCharEncCloseFunc(in
->encoder
);
2479 if (in
->closecallback
!= NULL
) {
2480 in
->closecallback(in
->context
);
2482 if (in
->buffer
!= NULL
) {
2483 xmlBufFree(in
->buffer
);
2490 #ifdef LIBXML_OUTPUT_ENABLED
2492 * xmlOutputBufferClose:
2493 * @out: a buffered output
2495 * flushes and close the output I/O channel
2496 * and free up all the associated resources
2498 * Returns the number of byte written or -1 in case of error.
2501 xmlOutputBufferClose(xmlOutputBufferPtr out
)
2508 if (out
->writecallback
!= NULL
)
2509 xmlOutputBufferFlush(out
);
2510 if (out
->closecallback
!= NULL
) {
2511 err_rc
= out
->closecallback(out
->context
);
2513 written
= out
->written
;
2515 xmlBufFree(out
->conv
);
2518 if (out
->encoder
!= NULL
) {
2519 xmlCharEncCloseFunc(out
->encoder
);
2521 if (out
->buffer
!= NULL
) {
2522 xmlBufFree(out
->buffer
);
2529 return ((err_rc
== 0) ? written
: err_rc
);
2531 #endif /* LIBXML_OUTPUT_ENABLED */
2533 xmlParserInputBufferPtr
2534 __xmlParserInputBufferCreateFilename(const char *URI
, xmlCharEncoding enc
) {
2535 xmlParserInputBufferPtr ret
;
2537 void *context
= NULL
;
2539 if (xmlInputCallbackInitialized
== 0)
2540 xmlRegisterDefaultInputCallbacks();
2542 if (URI
== NULL
) return(NULL
);
2545 * Try to find one of the input accept method accepting that scheme
2546 * Go in reverse to give precedence to user defined handlers.
2548 if (context
== NULL
) {
2549 for (i
= xmlInputCallbackNr
- 1;i
>= 0;i
--) {
2550 if ((xmlInputCallbackTable
[i
].matchcallback
!= NULL
) &&
2551 (xmlInputCallbackTable
[i
].matchcallback(URI
) != 0)) {
2552 context
= xmlInputCallbackTable
[i
].opencallback(URI
);
2553 if (context
!= NULL
) {
2559 if (context
== NULL
) {
2564 * Allocate the Input buffer front-end.
2566 ret
= xmlAllocParserInputBuffer(enc
);
2568 ret
->context
= context
;
2569 ret
->readcallback
= xmlInputCallbackTable
[i
].readcallback
;
2570 ret
->closecallback
= xmlInputCallbackTable
[i
].closecallback
;
2571 #ifdef LIBXML_ZLIB_ENABLED
2572 if ((xmlInputCallbackTable
[i
].opencallback
== xmlGzfileOpen
) &&
2573 (strcmp(URI
, "-") != 0)) {
2574 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
2575 ret
->compressed
= !gzdirect(context
);
2577 if (((z_stream
*)context
)->avail_in
> 4) {
2578 char *cptr
, buff4
[4];
2579 cptr
= (char *) ((z_stream
*)context
)->next_in
;
2580 if (gzread(context
, buff4
, 4) == 4) {
2581 if (strncmp(buff4
, cptr
, 4) == 0)
2582 ret
->compressed
= 0;
2584 ret
->compressed
= 1;
2591 #ifdef LIBXML_LZMA_ENABLED
2592 if ((xmlInputCallbackTable
[i
].opencallback
== xmlXzfileOpen
) &&
2593 (strcmp(URI
, "-") != 0)) {
2594 ret
->compressed
= __libxml2_xzcompressed(context
);
2599 xmlInputCallbackTable
[i
].closecallback (context
);
2605 * xmlParserInputBufferCreateFilename:
2606 * @URI: a C string containing the URI or filename
2607 * @enc: the charset encoding if known
2609 * Create a buffered parser input for the progressive parsing of a file
2610 * If filename is "-' then we use stdin as the input.
2611 * Automatic support for ZLIB/Compress compressed document is provided
2612 * by default if found at compile-time.
2613 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
2615 * Returns the new parser input or NULL
2617 xmlParserInputBufferPtr
2618 xmlParserInputBufferCreateFilename(const char *URI
, xmlCharEncoding enc
) {
2619 if ((xmlParserInputBufferCreateFilenameValue
)) {
2620 return xmlParserInputBufferCreateFilenameValue(URI
, enc
);
2622 return __xmlParserInputBufferCreateFilename(URI
, enc
);
2625 #ifdef LIBXML_OUTPUT_ENABLED
2627 __xmlOutputBufferCreateFilename(const char *URI
,
2628 xmlCharEncodingHandlerPtr encoder
,
2629 int compression ATTRIBUTE_UNUSED
) {
2630 xmlOutputBufferPtr ret
;
2633 void *context
= NULL
;
2634 char *unescaped
= NULL
;
2635 #ifdef LIBXML_ZLIB_ENABLED
2636 int is_file_uri
= 1;
2639 if (xmlOutputCallbackInitialized
== 0)
2640 xmlRegisterDefaultOutputCallbacks();
2642 if (URI
== NULL
) return(NULL
);
2644 puri
= xmlParseURI(URI
);
2646 #ifdef LIBXML_ZLIB_ENABLED
2647 if ((puri
->scheme
!= NULL
) &&
2648 (!xmlStrEqual(BAD_CAST puri
->scheme
, BAD_CAST
"file")))
2652 * try to limit the damages of the URI unescaping code.
2654 if ((puri
->scheme
== NULL
) ||
2655 (xmlStrEqual(BAD_CAST puri
->scheme
, BAD_CAST
"file")))
2656 unescaped
= xmlURIUnescapeString(URI
, 0, NULL
);
2661 * Try to find one of the output accept method accepting that scheme
2662 * Go in reverse to give precedence to user defined handlers.
2663 * try with an unescaped version of the URI
2665 if (unescaped
!= NULL
) {
2666 #ifdef LIBXML_ZLIB_ENABLED
2667 if ((compression
> 0) && (compression
<= 9) && (is_file_uri
== 1)) {
2668 context
= xmlGzfileOpenW(unescaped
, compression
);
2669 if (context
!= NULL
) {
2670 ret
= xmlAllocOutputBufferInternal(encoder
);
2672 ret
->context
= context
;
2673 ret
->writecallback
= xmlGzfileWrite
;
2674 ret
->closecallback
= xmlGzfileClose
;
2681 for (i
= xmlOutputCallbackNr
- 1;i
>= 0;i
--) {
2682 if ((xmlOutputCallbackTable
[i
].matchcallback
!= NULL
) &&
2683 (xmlOutputCallbackTable
[i
].matchcallback(unescaped
) != 0)) {
2684 #if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2685 /* Need to pass compression parameter into HTTP open calls */
2686 if (xmlOutputCallbackTable
[i
].matchcallback
== xmlIOHTTPMatch
)
2687 context
= xmlIOHTTPOpenW(unescaped
, compression
);
2690 context
= xmlOutputCallbackTable
[i
].opencallback(unescaped
);
2691 if (context
!= NULL
)
2699 * If this failed try with a non-escaped URI this may be a strange
2702 if (context
== NULL
) {
2703 #ifdef LIBXML_ZLIB_ENABLED
2704 if ((compression
> 0) && (compression
<= 9) && (is_file_uri
== 1)) {
2705 context
= xmlGzfileOpenW(URI
, compression
);
2706 if (context
!= NULL
) {
2707 ret
= xmlAllocOutputBufferInternal(encoder
);
2709 ret
->context
= context
;
2710 ret
->writecallback
= xmlGzfileWrite
;
2711 ret
->closecallback
= xmlGzfileClose
;
2717 for (i
= xmlOutputCallbackNr
- 1;i
>= 0;i
--) {
2718 if ((xmlOutputCallbackTable
[i
].matchcallback
!= NULL
) &&
2719 (xmlOutputCallbackTable
[i
].matchcallback(URI
) != 0)) {
2720 #if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2721 /* Need to pass compression parameter into HTTP open calls */
2722 if (xmlOutputCallbackTable
[i
].matchcallback
== xmlIOHTTPMatch
)
2723 context
= xmlIOHTTPOpenW(URI
, compression
);
2726 context
= xmlOutputCallbackTable
[i
].opencallback(URI
);
2727 if (context
!= NULL
)
2733 if (context
== NULL
) {
2738 * Allocate the Output buffer front-end.
2740 ret
= xmlAllocOutputBufferInternal(encoder
);
2742 ret
->context
= context
;
2743 ret
->writecallback
= xmlOutputCallbackTable
[i
].writecallback
;
2744 ret
->closecallback
= xmlOutputCallbackTable
[i
].closecallback
;
2750 * xmlOutputBufferCreateFilename:
2751 * @URI: a C string containing the URI or filename
2752 * @encoder: the encoding converter or NULL
2753 * @compression: the compression ration (0 none, 9 max).
2755 * Create a buffered output for the progressive saving of a file
2756 * If filename is "-' then we use stdout as the output.
2757 * Automatic support for ZLIB/Compress compressed document is provided
2758 * by default if found at compile-time.
2759 * TODO: currently if compression is set, the library only support
2760 * writing to a local file.
2762 * Returns the new output or NULL
2765 xmlOutputBufferCreateFilename(const char *URI
,
2766 xmlCharEncodingHandlerPtr encoder
,
2767 int compression ATTRIBUTE_UNUSED
) {
2768 if ((xmlOutputBufferCreateFilenameValue
)) {
2769 return xmlOutputBufferCreateFilenameValue(URI
, encoder
, compression
);
2771 return __xmlOutputBufferCreateFilename(URI
, encoder
, compression
);
2773 #endif /* LIBXML_OUTPUT_ENABLED */
2776 * xmlParserInputBufferCreateFile:
2778 * @enc: the charset encoding if known
2780 * Create a buffered parser input for the progressive parsing of a FILE *
2783 * Returns the new parser input or NULL
2785 xmlParserInputBufferPtr
2786 xmlParserInputBufferCreateFile(FILE *file
, xmlCharEncoding enc
) {
2787 xmlParserInputBufferPtr ret
;
2789 if (xmlInputCallbackInitialized
== 0)
2790 xmlRegisterDefaultInputCallbacks();
2792 if (file
== NULL
) return(NULL
);
2794 ret
= xmlAllocParserInputBuffer(enc
);
2796 ret
->context
= file
;
2797 ret
->readcallback
= xmlFileRead
;
2798 ret
->closecallback
= xmlFileFlush
;
2804 #ifdef LIBXML_OUTPUT_ENABLED
2806 * xmlOutputBufferCreateFile:
2808 * @encoder: the encoding converter or NULL
2810 * Create a buffered output for the progressive saving to a FILE *
2813 * Returns the new parser output or NULL
2816 xmlOutputBufferCreateFile(FILE *file
, xmlCharEncodingHandlerPtr encoder
) {
2817 xmlOutputBufferPtr ret
;
2819 if (xmlOutputCallbackInitialized
== 0)
2820 xmlRegisterDefaultOutputCallbacks();
2822 if (file
== NULL
) return(NULL
);
2824 ret
= xmlAllocOutputBufferInternal(encoder
);
2826 ret
->context
= file
;
2827 ret
->writecallback
= xmlFileWrite
;
2828 ret
->closecallback
= xmlFileFlush
;
2835 * xmlOutputBufferCreateBuffer:
2836 * @buffer: a xmlBufferPtr
2837 * @encoder: the encoding converter or NULL
2839 * Create a buffered output for the progressive saving to a xmlBuffer
2841 * Returns the new parser output or NULL
2844 xmlOutputBufferCreateBuffer(xmlBufferPtr buffer
,
2845 xmlCharEncodingHandlerPtr encoder
) {
2846 xmlOutputBufferPtr ret
;
2848 if (buffer
== NULL
) return(NULL
);
2850 ret
= xmlOutputBufferCreateIO(xmlBufferWrite
, NULL
, (void *) buffer
,
2857 * xmlOutputBufferGetContent:
2858 * @out: an xmlOutputBufferPtr
2860 * Gives a pointer to the data currently held in the output buffer
2862 * Returns a pointer to the data or NULL in case of error
2865 xmlOutputBufferGetContent(xmlOutputBufferPtr out
) {
2866 if ((out
== NULL
) || (out
->buffer
== NULL
))
2869 return(xmlBufContent(out
->buffer
));
2873 * xmlOutputBufferGetSize:
2874 * @out: an xmlOutputBufferPtr
2876 * Gives the length of the data currently held in the output buffer
2878 * Returns 0 in case or error or no data is held, the size otherwise
2881 xmlOutputBufferGetSize(xmlOutputBufferPtr out
) {
2882 if ((out
== NULL
) || (out
->buffer
== NULL
))
2885 return(xmlBufUse(out
->buffer
));
2889 #endif /* LIBXML_OUTPUT_ENABLED */
2892 * xmlParserInputBufferCreateFd:
2893 * @fd: a file descriptor number
2894 * @enc: the charset encoding if known
2896 * Create a buffered parser input for the progressive parsing for the input
2897 * from a file descriptor
2899 * Returns the new parser input or NULL
2901 xmlParserInputBufferPtr
2902 xmlParserInputBufferCreateFd(int fd
, xmlCharEncoding enc
) {
2903 xmlParserInputBufferPtr ret
;
2905 if (fd
< 0) return(NULL
);
2907 ret
= xmlAllocParserInputBuffer(enc
);
2909 ret
->context
= (void *) (ptrdiff_t) fd
;
2910 ret
->readcallback
= xmlFdRead
;
2911 ret
->closecallback
= xmlFdClose
;
2918 * xmlParserInputBufferCreateMem:
2919 * @mem: the memory input
2920 * @size: the length of the memory block
2921 * @enc: the charset encoding if known
2923 * Create a buffered parser input for the progressive parsing for the input
2924 * from a memory area.
2926 * Returns the new parser input or NULL
2928 xmlParserInputBufferPtr
2929 xmlParserInputBufferCreateMem(const char *mem
, int size
, xmlCharEncoding enc
) {
2930 xmlParserInputBufferPtr ret
;
2933 if (size
< 0) return(NULL
);
2934 if (mem
== NULL
) return(NULL
);
2936 ret
= xmlAllocParserInputBuffer(enc
);
2938 ret
->context
= (void *) mem
;
2939 ret
->readcallback
= xmlInputReadCallbackNop
;
2940 ret
->closecallback
= NULL
;
2941 errcode
= xmlBufAdd(ret
->buffer
, (const xmlChar
*) mem
, size
);
2952 * xmlParserInputBufferCreateStatic:
2953 * @mem: the memory input
2954 * @size: the length of the memory block
2955 * @enc: the charset encoding if known
2957 * Create a buffered parser input for the progressive parsing for the input
2958 * from an immutable memory area. This will not copy the memory area to
2959 * the buffer, but the memory is expected to be available until the end of
2960 * the parsing, this is useful for example when using mmap'ed file.
2962 * Returns the new parser input or NULL
2964 xmlParserInputBufferPtr
2965 xmlParserInputBufferCreateStatic(const char *mem
, int size
,
2966 xmlCharEncoding enc
) {
2967 xmlParserInputBufferPtr ret
;
2969 if (size
< 0) return(NULL
);
2970 if (mem
== NULL
) return(NULL
);
2972 ret
= (xmlParserInputBufferPtr
) xmlMalloc(sizeof(xmlParserInputBuffer
));
2974 xmlIOErrMemory("creating input buffer");
2977 memset(ret
, 0, (size_t) sizeof(xmlParserInputBuffer
));
2978 ret
->buffer
= xmlBufCreateStatic((void *)mem
, (size_t) size
);
2979 if (ret
->buffer
== NULL
) {
2983 ret
->encoder
= xmlGetCharEncodingHandler(enc
);
2984 if (ret
->encoder
!= NULL
)
2985 ret
->raw
= xmlBufCreateSize(2 * xmlDefaultBufferSize
);
2988 ret
->compressed
= -1;
2989 ret
->context
= (void *) mem
;
2990 ret
->readcallback
= NULL
;
2991 ret
->closecallback
= NULL
;
2996 #ifdef LIBXML_OUTPUT_ENABLED
2998 * xmlOutputBufferCreateFd:
2999 * @fd: a file descriptor number
3000 * @encoder: the encoding converter or NULL
3002 * Create a buffered output for the progressive saving
3003 * to a file descriptor
3005 * Returns the new parser output or NULL
3008 xmlOutputBufferCreateFd(int fd
, xmlCharEncodingHandlerPtr encoder
) {
3009 xmlOutputBufferPtr ret
;
3011 if (fd
< 0) return(NULL
);
3013 ret
= xmlAllocOutputBufferInternal(encoder
);
3015 ret
->context
= (void *) (ptrdiff_t) fd
;
3016 ret
->writecallback
= xmlFdWrite
;
3017 ret
->closecallback
= NULL
;
3022 #endif /* LIBXML_OUTPUT_ENABLED */
3025 * xmlParserInputBufferCreateIO:
3026 * @ioread: an I/O read function
3027 * @ioclose: an I/O close function
3028 * @ioctx: an I/O handler
3029 * @enc: the charset encoding if known
3031 * Create a buffered parser input for the progressive parsing for the input
3032 * from an I/O handler
3034 * Returns the new parser input or NULL
3036 xmlParserInputBufferPtr
3037 xmlParserInputBufferCreateIO(xmlInputReadCallback ioread
,
3038 xmlInputCloseCallback ioclose
, void *ioctx
, xmlCharEncoding enc
) {
3039 xmlParserInputBufferPtr ret
;
3041 if (ioread
== NULL
) return(NULL
);
3043 ret
= xmlAllocParserInputBuffer(enc
);
3045 ret
->context
= (void *) ioctx
;
3046 ret
->readcallback
= ioread
;
3047 ret
->closecallback
= ioclose
;
3053 #ifdef LIBXML_OUTPUT_ENABLED
3055 * xmlOutputBufferCreateIO:
3056 * @iowrite: an I/O write function
3057 * @ioclose: an I/O close function
3058 * @ioctx: an I/O handler
3059 * @encoder: the charset encoding if known
3061 * Create a buffered output for the progressive saving
3064 * Returns the new parser output or NULL
3067 xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite
,
3068 xmlOutputCloseCallback ioclose
, void *ioctx
,
3069 xmlCharEncodingHandlerPtr encoder
) {
3070 xmlOutputBufferPtr ret
;
3072 if (iowrite
== NULL
) return(NULL
);
3074 ret
= xmlAllocOutputBufferInternal(encoder
);
3076 ret
->context
= (void *) ioctx
;
3077 ret
->writecallback
= iowrite
;
3078 ret
->closecallback
= ioclose
;
3083 #endif /* LIBXML_OUTPUT_ENABLED */
3086 * xmlParserInputBufferCreateFilenameDefault:
3087 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
3089 * Registers a callback for URI input file handling
3091 * Returns the old value of the registration function
3093 xmlParserInputBufferCreateFilenameFunc
3094 xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func
)
3096 xmlParserInputBufferCreateFilenameFunc old
= xmlParserInputBufferCreateFilenameValue
;
3098 old
= __xmlParserInputBufferCreateFilename
;
3101 xmlParserInputBufferCreateFilenameValue
= func
;
3106 * xmlOutputBufferCreateFilenameDefault:
3107 * @func: function pointer to the new OutputBufferCreateFilenameFunc
3109 * Registers a callback for URI output file handling
3111 * Returns the old value of the registration function
3113 xmlOutputBufferCreateFilenameFunc
3114 xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func
)
3116 xmlOutputBufferCreateFilenameFunc old
= xmlOutputBufferCreateFilenameValue
;
3117 #ifdef LIBXML_OUTPUT_ENABLED
3119 old
= __xmlOutputBufferCreateFilename
;
3122 xmlOutputBufferCreateFilenameValue
= func
;
3127 * xmlParserInputBufferPush:
3128 * @in: a buffered parser input
3129 * @len: the size in bytes of the array.
3130 * @buf: an char array
3132 * Push the content of the arry in the input buffer
3133 * This routine handle the I18N transcoding to internal UTF-8
3134 * This is used when operating the parser in progressive (push) mode.
3136 * Returns the number of chars read and stored in the buffer, or -1
3140 xmlParserInputBufferPush(xmlParserInputBufferPtr in
,
3141 int len
, const char *buf
) {
3145 if (len
< 0) return(0);
3146 if ((in
== NULL
) || (in
->error
)) return(-1);
3147 if (in
->encoder
!= NULL
) {
3151 * Store the data in the incoming raw buffer
3153 if (in
->raw
== NULL
) {
3154 in
->raw
= xmlBufCreate();
3156 ret
= xmlBufAdd(in
->raw
, (const xmlChar
*) buf
, len
);
3161 * convert as much as possible to the parser reading buffer.
3163 use
= xmlBufUse(in
->raw
);
3164 nbchars
= xmlCharEncInput(in
, 1);
3166 xmlIOErr(XML_IO_ENCODER
, NULL
);
3167 in
->error
= XML_IO_ENCODER
;
3170 in
->rawconsumed
+= (use
- xmlBufUse(in
->raw
));
3173 ret
= xmlBufAdd(in
->buffer
, (xmlChar
*) buf
, nbchars
);
3178 xmlGenericError(xmlGenericErrorContext
,
3179 "I/O: pushed %d chars, buffer %d/%d\n",
3180 nbchars
, xmlBufUse(in
->buffer
), xmlBufLength(in
->buffer
));
3188 * When reading from an Input channel indicated end of file or error
3189 * don't reread from it again.
3192 endOfInput (void * context ATTRIBUTE_UNUSED
,
3193 char * buffer ATTRIBUTE_UNUSED
,
3194 int len ATTRIBUTE_UNUSED
) {
3199 * xmlParserInputBufferGrow:
3200 * @in: a buffered parser input
3201 * @len: indicative value of the amount of chars to read
3203 * Grow up the content of the input buffer, the old data are preserved
3204 * This routine handle the I18N transcoding to internal UTF-8
3205 * This routine is used when operating the parser in normal (pull) mode
3207 * TODO: one should be able to remove one extra copy by copying directly
3208 * onto in->buffer or in->raw
3210 * Returns the number of chars read and stored in the buffer, or -1
3214 xmlParserInputBufferGrow(xmlParserInputBufferPtr in
, int len
) {
3215 char *buffer
= NULL
;
3219 if ((in
== NULL
) || (in
->error
)) return(-1);
3220 if ((len
<= MINLEN
) && (len
!= 4))
3223 if (xmlBufAvail(in
->buffer
) <= 0) {
3224 xmlIOErr(XML_IO_BUFFER_FULL
, NULL
);
3225 in
->error
= XML_IO_BUFFER_FULL
;
3229 if (xmlBufGrow(in
->buffer
, len
+ 1) < 0) {
3230 xmlIOErrMemory("growing input buffer");
3231 in
->error
= XML_ERR_NO_MEMORY
;
3234 buffer
= (char *)xmlBufEnd(in
->buffer
);
3237 * Call the read method for this I/O type.
3239 if (in
->readcallback
!= NULL
) {
3240 res
= in
->readcallback(in
->context
, &buffer
[0], len
);
3242 in
->readcallback
= endOfInput
;
3244 xmlIOErr(XML_IO_NO_INPUT
, NULL
);
3245 in
->error
= XML_IO_NO_INPUT
;
3253 * try to establish compressed status of input if not done already
3255 if (in
->compressed
== -1) {
3256 #ifdef LIBXML_LZMA_ENABLED
3257 if (in
->readcallback
== xmlXzfileRead
)
3258 in
->compressed
= __libxml2_xzcompressed(in
->context
);
3263 if (in
->encoder
!= NULL
) {
3267 * Store the data in the incoming raw buffer
3269 if (in
->raw
== NULL
) {
3270 in
->raw
= xmlBufCreate();
3272 res
= xmlBufAdd(in
->raw
, (const xmlChar
*) buffer
, len
);
3277 * convert as much as possible to the parser reading buffer.
3279 use
= xmlBufUse(in
->raw
);
3280 nbchars
= xmlCharEncInput(in
, 1);
3282 xmlIOErr(XML_IO_ENCODER
, NULL
);
3283 in
->error
= XML_IO_ENCODER
;
3286 in
->rawconsumed
+= (use
- xmlBufUse(in
->raw
));
3289 xmlBufAddLen(in
->buffer
, nbchars
);
3292 xmlGenericError(xmlGenericErrorContext
,
3293 "I/O: read %d chars, buffer %d\n",
3294 nbchars
, xmlBufUse(in
->buffer
));
3300 * xmlParserInputBufferRead:
3301 * @in: a buffered parser input
3302 * @len: indicative value of the amount of chars to read
3304 * Refresh the content of the input buffer, the old data are considered
3306 * This routine handle the I18N transcoding to internal UTF-8
3308 * Returns the number of chars read and stored in the buffer, or -1
3312 xmlParserInputBufferRead(xmlParserInputBufferPtr in
, int len
) {
3313 if ((in
== NULL
) || (in
->error
)) return(-1);
3314 if (in
->readcallback
!= NULL
)
3315 return(xmlParserInputBufferGrow(in
, len
));
3316 else if (xmlBufGetAllocationScheme(in
->buffer
) == XML_BUFFER_ALLOC_IMMUTABLE
)
3322 #ifdef LIBXML_OUTPUT_ENABLED
3324 * xmlOutputBufferWrite:
3325 * @out: a buffered parser output
3326 * @len: the size in bytes of the array.
3327 * @buf: an char array
3329 * Write the content of the array in the output I/O buffer
3330 * This routine handle the I18N transcoding from internal UTF-8
3331 * The buffer is lossless, i.e. will store in case of partial
3332 * or delayed writes.
3334 * Returns the number of chars immediately written, or -1
3338 xmlOutputBufferWrite(xmlOutputBufferPtr out
, int len
, const char *buf
) {
3339 int nbchars
= 0; /* number of chars to output to I/O */
3340 int ret
; /* return from function call */
3341 int written
= 0; /* number of char written to I/O so far */
3342 int chunk
; /* number of byte curreent processed from buf */
3344 if ((out
== NULL
) || (out
->error
)) return(-1);
3345 if (len
< 0) return(0);
3346 if (out
->error
) return(-1);
3350 if (chunk
> 4 * MINLEN
)
3354 * first handle encoding stuff.
3356 if (out
->encoder
!= NULL
) {
3358 * Store the data in the incoming raw buffer
3360 if (out
->conv
== NULL
) {
3361 out
->conv
= xmlBufCreate();
3363 ret
= xmlBufAdd(out
->buffer
, (const xmlChar
*) buf
, chunk
);
3367 if ((xmlBufUse(out
->buffer
) < MINLEN
) && (chunk
== len
))
3371 * convert as much as possible to the parser reading buffer.
3373 ret
= xmlCharEncOutput(out
, 0);
3374 if ((ret
< 0) && (ret
!= -3)) {
3375 xmlIOErr(XML_IO_ENCODER
, NULL
);
3376 out
->error
= XML_IO_ENCODER
;
3379 nbchars
= xmlBufUse(out
->conv
);
3381 ret
= xmlBufAdd(out
->buffer
, (const xmlChar
*) buf
, chunk
);
3384 nbchars
= xmlBufUse(out
->buffer
);
3389 if ((nbchars
< MINLEN
) && (len
<= 0))
3392 if (out
->writecallback
) {
3394 * second write the stuff to the I/O channel
3396 if (out
->encoder
!= NULL
) {
3397 ret
= out
->writecallback(out
->context
,
3398 (const char *)xmlBufContent(out
->conv
), nbchars
);
3400 xmlBufShrink(out
->conv
, ret
);
3402 ret
= out
->writecallback(out
->context
,
3403 (const char *)xmlBufContent(out
->buffer
), nbchars
);
3405 xmlBufShrink(out
->buffer
, ret
);
3408 xmlIOErr(XML_IO_WRITE
, NULL
);
3409 out
->error
= XML_IO_WRITE
;
3412 out
->written
+= ret
;
3419 xmlGenericError(xmlGenericErrorContext
,
3420 "I/O: wrote %d chars\n", written
);
3427 * @out: a pointer to an array of bytes to store the result
3428 * @outlen: the length of @out
3429 * @in: a pointer to an array of unescaped UTF-8 bytes
3430 * @inlen: the length of @in
3432 * Take a block of UTF-8 chars in and escape them.
3433 * Returns 0 if success, or -1 otherwise
3434 * The value of @inlen after return is the number of octets consumed
3435 * if the return value is positive, else unpredictable.
3436 * The value of @outlen after return is the number of octets consumed.
3439 xmlEscapeContent(unsigned char* out
, int *outlen
,
3440 const xmlChar
* in
, int *inlen
) {
3441 unsigned char* outstart
= out
;
3442 const unsigned char* base
= in
;
3443 unsigned char* outend
= out
+ *outlen
;
3444 const unsigned char* inend
;
3446 inend
= in
+ (*inlen
);
3448 while ((in
< inend
) && (out
< outend
)) {
3450 if (outend
- out
< 4) break;
3455 } else if (*in
== '>') {
3456 if (outend
- out
< 4) break;
3461 } else if (*in
== '&') {
3462 if (outend
- out
< 5) break;
3468 } else if (*in
== '\r') {
3469 if (outend
- out
< 5) break;
3476 *out
++ = (unsigned char) *in
;
3480 *outlen
= out
- outstart
;
3486 * xmlOutputBufferWriteEscape:
3487 * @out: a buffered parser output
3488 * @str: a zero terminated UTF-8 string
3489 * @escaping: an optional escaping function (or NULL)
3491 * Write the content of the string in the output I/O buffer
3492 * This routine escapes the caracters and then handle the I18N
3493 * transcoding from internal UTF-8
3494 * The buffer is lossless, i.e. will store in case of partial
3495 * or delayed writes.
3497 * Returns the number of chars immediately written, or -1
3501 xmlOutputBufferWriteEscape(xmlOutputBufferPtr out
, const xmlChar
*str
,
3502 xmlCharEncodingOutputFunc escaping
) {
3503 int nbchars
= 0; /* number of chars to output to I/O */
3504 int ret
; /* return from function call */
3505 int written
= 0; /* number of char written to I/O so far */
3506 int oldwritten
=0;/* loop guard */
3507 int chunk
; /* number of byte currently processed from str */
3508 int len
; /* number of bytes in str */
3509 int cons
; /* byte from str consumed */
3511 if ((out
== NULL
) || (out
->error
) || (str
== NULL
) ||
3512 (out
->buffer
== NULL
) ||
3513 (xmlBufGetAllocationScheme(out
->buffer
) == XML_BUFFER_ALLOC_IMMUTABLE
))
3515 len
= strlen((const char *)str
);
3516 if (len
< 0) return(0);
3517 if (out
->error
) return(-1);
3518 if (escaping
== NULL
) escaping
= xmlEscapeContent
;
3521 oldwritten
= written
;
3524 * how many bytes to consume and how many bytes to store.
3527 chunk
= xmlBufAvail(out
->buffer
) - 1;
3530 * make sure we have enough room to save first, if this is
3531 * not the case force a flush, but make sure we stay in the loop
3534 if (xmlBufGrow(out
->buffer
, 100) < 0)
3541 * first handle encoding stuff.
3543 if (out
->encoder
!= NULL
) {
3545 * Store the data in the incoming raw buffer
3547 if (out
->conv
== NULL
) {
3548 out
->conv
= xmlBufCreate();
3550 ret
= escaping(xmlBufEnd(out
->buffer
) ,
3551 &chunk
, str
, &cons
);
3552 if ((ret
< 0) || (chunk
== 0)) /* chunk==0 => nothing done */
3554 xmlBufAddLen(out
->buffer
, chunk
);
3556 if ((xmlBufUse(out
->buffer
) < MINLEN
) && (cons
== len
))
3560 * convert as much as possible to the output buffer.
3562 ret
= xmlCharEncOutput(out
, 0);
3563 if ((ret
< 0) && (ret
!= -3)) {
3564 xmlIOErr(XML_IO_ENCODER
, NULL
);
3565 out
->error
= XML_IO_ENCODER
;
3568 nbchars
= xmlBufUse(out
->conv
);
3570 ret
= escaping(xmlBufEnd(out
->buffer
), &chunk
, str
, &cons
);
3571 if ((ret
< 0) || (chunk
== 0)) /* chunk==0 => nothing done */
3573 xmlBufAddLen(out
->buffer
, chunk
);
3574 nbchars
= xmlBufUse(out
->buffer
);
3579 if ((nbchars
< MINLEN
) && (len
<= 0))
3582 if (out
->writecallback
) {
3584 * second write the stuff to the I/O channel
3586 if (out
->encoder
!= NULL
) {
3587 ret
= out
->writecallback(out
->context
,
3588 (const char *)xmlBufContent(out
->conv
), nbchars
);
3590 xmlBufShrink(out
->conv
, ret
);
3592 ret
= out
->writecallback(out
->context
,
3593 (const char *)xmlBufContent(out
->buffer
), nbchars
);
3595 xmlBufShrink(out
->buffer
, ret
);
3598 xmlIOErr(XML_IO_WRITE
, NULL
);
3599 out
->error
= XML_IO_WRITE
;
3602 out
->written
+= ret
;
3603 } else if (xmlBufAvail(out
->buffer
) < MINLEN
) {
3604 xmlBufGrow(out
->buffer
, MINLEN
);
3607 } while ((len
> 0) && (oldwritten
!= written
));
3611 xmlGenericError(xmlGenericErrorContext
,
3612 "I/O: wrote %d chars\n", written
);
3618 * xmlOutputBufferWriteString:
3619 * @out: a buffered parser output
3620 * @str: a zero terminated C string
3622 * Write the content of the string in the output I/O buffer
3623 * This routine handle the I18N transcoding from internal UTF-8
3624 * The buffer is lossless, i.e. will store in case of partial
3625 * or delayed writes.
3627 * Returns the number of chars immediately written, or -1
3631 xmlOutputBufferWriteString(xmlOutputBufferPtr out
, const char *str
) {
3634 if ((out
== NULL
) || (out
->error
)) return(-1);
3640 return(xmlOutputBufferWrite(out
, len
, str
));
3645 * xmlOutputBufferFlush:
3646 * @out: a buffered output
3648 * flushes the output I/O channel
3650 * Returns the number of byte written or -1 in case of error.
3653 xmlOutputBufferFlush(xmlOutputBufferPtr out
) {
3654 int nbchars
= 0, ret
= 0;
3656 if ((out
== NULL
) || (out
->error
)) return(-1);
3658 * first handle encoding stuff.
3660 if ((out
->conv
!= NULL
) && (out
->encoder
!= NULL
)) {
3662 * convert as much as possible to the parser output buffer.
3665 nbchars
= xmlCharEncOutput(out
, 0);
3667 xmlIOErr(XML_IO_ENCODER
, NULL
);
3668 out
->error
= XML_IO_ENCODER
;
3675 * second flush the stuff to the I/O channel
3677 if ((out
->conv
!= NULL
) && (out
->encoder
!= NULL
) &&
3678 (out
->writecallback
!= NULL
)) {
3679 ret
= out
->writecallback(out
->context
,
3680 (const char *)xmlBufContent(out
->conv
),
3681 xmlBufUse(out
->conv
));
3683 xmlBufShrink(out
->conv
, ret
);
3684 } else if (out
->writecallback
!= NULL
) {
3685 ret
= out
->writecallback(out
->context
,
3686 (const char *)xmlBufContent(out
->buffer
),
3687 xmlBufUse(out
->buffer
));
3689 xmlBufShrink(out
->buffer
, ret
);
3692 xmlIOErr(XML_IO_FLUSH
, NULL
);
3693 out
->error
= XML_IO_FLUSH
;
3696 out
->written
+= ret
;
3699 xmlGenericError(xmlGenericErrorContext
,
3700 "I/O: flushed %d chars\n", ret
);
3704 #endif /* LIBXML_OUTPUT_ENABLED */
3707 * xmlParserGetDirectory:
3708 * @filename: the path to a file
3710 * lookup the directory for that file
3712 * Returns a new allocated string containing the directory, or NULL.
3715 xmlParserGetDirectory(const char *filename
) {
3720 #ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */
3724 if (xmlInputCallbackInitialized
== 0)
3725 xmlRegisterDefaultInputCallbacks();
3727 if (filename
== NULL
) return(NULL
);
3729 #if defined(_WIN32) && !defined(__CYGWIN__)
3730 # define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
3732 # define IS_XMLPGD_SEP(ch) (ch=='/')
3735 strncpy(dir
, filename
, 1023);
3737 cur
= &dir
[strlen(dir
)];
3739 if (IS_XMLPGD_SEP(*cur
)) break;
3742 if (IS_XMLPGD_SEP(*cur
)) {
3743 if (cur
== dir
) dir
[1] = 0;
3745 ret
= xmlMemStrdup(dir
);
3747 if (getcwd(dir
, 1024) != NULL
) {
3749 ret
= xmlMemStrdup(dir
);
3753 #undef IS_XMLPGD_SEP
3756 /****************************************************************
3758 * External entities loading *
3760 ****************************************************************/
3763 * xmlCheckHTTPInput:
3764 * @ctxt: an XML parser context
3765 * @ret: an XML parser input
3767 * Check an input in case it was created from an HTTP stream, in that
3768 * case it will handle encoding and update of the base URL in case of
3769 * redirection. It also checks for HTTP errors in which case the input
3770 * is cleanly freed up and an appropriate error is raised in context
3772 * Returns the input or NULL in case of HTTP error.
3775 xmlCheckHTTPInput(xmlParserCtxtPtr ctxt
, xmlParserInputPtr ret
) {
3776 #ifdef LIBXML_HTTP_ENABLED
3777 if ((ret
!= NULL
) && (ret
->buf
!= NULL
) &&
3778 (ret
->buf
->readcallback
== xmlIOHTTPRead
) &&
3779 (ret
->buf
->context
!= NULL
)) {
3780 const char *encoding
;
3785 code
= xmlNanoHTTPReturnCode(ret
->buf
->context
);
3788 if (ret
->filename
!= NULL
)
3789 __xmlLoaderErr(ctxt
, "failed to load HTTP resource \"%s\"\n",
3790 (const char *) ret
->filename
);
3792 __xmlLoaderErr(ctxt
, "failed to load HTTP resource\n", NULL
);
3793 xmlFreeInputStream(ret
);
3797 mime
= xmlNanoHTTPMimeType(ret
->buf
->context
);
3798 if ((xmlStrstr(BAD_CAST mime
, BAD_CAST
"/xml")) ||
3799 (xmlStrstr(BAD_CAST mime
, BAD_CAST
"+xml"))) {
3800 encoding
= xmlNanoHTTPEncoding(ret
->buf
->context
);
3801 if (encoding
!= NULL
) {
3802 xmlCharEncodingHandlerPtr handler
;
3804 handler
= xmlFindCharEncodingHandler(encoding
);
3805 if (handler
!= NULL
) {
3806 xmlSwitchInputEncoding(ctxt
, ret
, handler
);
3808 __xmlErrEncoding(ctxt
, XML_ERR_UNKNOWN_ENCODING
,
3809 "Unknown encoding %s",
3810 BAD_CAST encoding
, NULL
);
3812 if (ret
->encoding
== NULL
)
3813 ret
->encoding
= xmlStrdup(BAD_CAST encoding
);
3816 } else if (xmlStrstr(BAD_CAST mime
, BAD_CAST
"html")) {
3819 redir
= xmlNanoHTTPRedir(ret
->buf
->context
);
3820 if (redir
!= NULL
) {
3821 if (ret
->filename
!= NULL
)
3822 xmlFree((xmlChar
*) ret
->filename
);
3823 if (ret
->directory
!= NULL
) {
3824 xmlFree((xmlChar
*) ret
->directory
);
3825 ret
->directory
= NULL
;
3828 (char *) xmlStrdup((const xmlChar
*) redir
);
3836 static int xmlNoNetExists(const char *URL
) {
3842 if (!xmlStrncasecmp(BAD_CAST URL
, BAD_CAST
"file://localhost/", 17))
3843 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3848 else if (!xmlStrncasecmp(BAD_CAST URL
, BAD_CAST
"file:///", 8)) {
3849 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3857 return xmlCheckFilename(path
);
3860 #ifdef LIBXML_CATALOG_ENABLED
3863 * xmlResolveResourceFromCatalog:
3864 * @URL: the URL for the entity to load
3865 * @ID: the System ID for the entity to load
3866 * @ctxt: the context in which the entity is called or NULL
3868 * Resolves the URL and ID against the appropriate catalog.
3869 * This function is used by xmlDefaultExternalEntityLoader and
3870 * xmlNoNetExternalEntityLoader.
3872 * Returns a new allocated URL, or NULL.
3875 xmlResolveResourceFromCatalog(const char *URL
, const char *ID
,
3876 xmlParserCtxtPtr ctxt
) {
3877 xmlChar
*resource
= NULL
;
3878 xmlCatalogAllow pref
;
3881 * If the resource doesn't exists as a file,
3882 * try to load it from the resource pointed in the catalogs
3884 pref
= xmlCatalogGetDefaults();
3886 if ((pref
!= XML_CATA_ALLOW_NONE
) && (!xmlNoNetExists(URL
))) {
3890 if ((ctxt
!= NULL
) && (ctxt
->catalogs
!= NULL
) &&
3891 ((pref
== XML_CATA_ALLOW_ALL
) ||
3892 (pref
== XML_CATA_ALLOW_DOCUMENT
))) {
3893 resource
= xmlCatalogLocalResolve(ctxt
->catalogs
,
3894 (const xmlChar
*)ID
,
3895 (const xmlChar
*)URL
);
3898 * Try a global lookup
3900 if ((resource
== NULL
) &&
3901 ((pref
== XML_CATA_ALLOW_ALL
) ||
3902 (pref
== XML_CATA_ALLOW_GLOBAL
))) {
3903 resource
= xmlCatalogResolve((const xmlChar
*)ID
,
3904 (const xmlChar
*)URL
);
3906 if ((resource
== NULL
) && (URL
!= NULL
))
3907 resource
= xmlStrdup((const xmlChar
*) URL
);
3910 * TODO: do an URI lookup on the reference
3912 if ((resource
!= NULL
) && (!xmlNoNetExists((const char *)resource
))) {
3913 xmlChar
*tmp
= NULL
;
3915 if ((ctxt
!= NULL
) && (ctxt
->catalogs
!= NULL
) &&
3916 ((pref
== XML_CATA_ALLOW_ALL
) ||
3917 (pref
== XML_CATA_ALLOW_DOCUMENT
))) {
3918 tmp
= xmlCatalogLocalResolveURI(ctxt
->catalogs
, resource
);
3920 if ((tmp
== NULL
) &&
3921 ((pref
== XML_CATA_ALLOW_ALL
) ||
3922 (pref
== XML_CATA_ALLOW_GLOBAL
))) {
3923 tmp
= xmlCatalogResolveURI(resource
);
3939 * xmlDefaultExternalEntityLoader:
3940 * @URL: the URL for the entity to load
3941 * @ID: the System ID for the entity to load
3942 * @ctxt: the context in which the entity is called or NULL
3944 * By default we don't load external entitites, yet.
3946 * Returns a new allocated xmlParserInputPtr, or NULL.
3948 static xmlParserInputPtr
3949 xmlDefaultExternalEntityLoader(const char *URL
, const char *ID
,
3950 xmlParserCtxtPtr ctxt
)
3952 xmlParserInputPtr ret
= NULL
;
3953 xmlChar
*resource
= NULL
;
3955 #ifdef DEBUG_EXTERNAL_ENTITIES
3956 xmlGenericError(xmlGenericErrorContext
,
3957 "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL
);
3959 if ((ctxt
!= NULL
) && (ctxt
->options
& XML_PARSE_NONET
)) {
3960 int options
= ctxt
->options
;
3962 ctxt
->options
-= XML_PARSE_NONET
;
3963 ret
= xmlNoNetExternalEntityLoader(URL
, ID
, ctxt
);
3964 ctxt
->options
= options
;
3967 #ifdef LIBXML_CATALOG_ENABLED
3968 resource
= xmlResolveResourceFromCatalog(URL
, ID
, ctxt
);
3971 if (resource
== NULL
)
3972 resource
= (xmlChar
*) URL
;
3974 if (resource
== NULL
) {
3977 __xmlLoaderErr(ctxt
, "failed to load external entity \"%s\"\n", ID
);
3980 ret
= xmlNewInputFromFile(ctxt
, (const char *) resource
);
3981 if ((resource
!= NULL
) && (resource
!= (xmlChar
*) URL
))
3986 static xmlExternalEntityLoader xmlCurrentExternalEntityLoader
=
3987 xmlDefaultExternalEntityLoader
;
3990 * xmlSetExternalEntityLoader:
3991 * @f: the new entity resolver function
3993 * Changes the defaultexternal entity resolver function for the application
3996 xmlSetExternalEntityLoader(xmlExternalEntityLoader f
) {
3997 xmlCurrentExternalEntityLoader
= f
;
4001 * xmlGetExternalEntityLoader:
4003 * Get the default external entity resolver function for the application
4005 * Returns the xmlExternalEntityLoader function pointer
4007 xmlExternalEntityLoader
4008 xmlGetExternalEntityLoader(void) {
4009 return(xmlCurrentExternalEntityLoader
);
4013 * xmlLoadExternalEntity:
4014 * @URL: the URL for the entity to load
4015 * @ID: the Public ID for the entity to load
4016 * @ctxt: the context in which the entity is called or NULL
4018 * Load an external entity, note that the use of this function for
4019 * unparsed entities may generate problems
4021 * Returns the xmlParserInputPtr or NULL
4024 xmlLoadExternalEntity(const char *URL
, const char *ID
,
4025 xmlParserCtxtPtr ctxt
) {
4026 if ((URL
!= NULL
) && (xmlNoNetExists(URL
) == 0)) {
4027 char *canonicFilename
;
4028 xmlParserInputPtr ret
;
4030 canonicFilename
= (char *) xmlCanonicPath((const xmlChar
*) URL
);
4031 if (canonicFilename
== NULL
) {
4032 xmlIOErrMemory("building canonical path\n");
4036 ret
= xmlCurrentExternalEntityLoader(canonicFilename
, ID
, ctxt
);
4037 xmlFree(canonicFilename
);
4040 return(xmlCurrentExternalEntityLoader(URL
, ID
, ctxt
));
4043 /************************************************************************
4045 * Disabling Network access *
4047 ************************************************************************/
4050 * xmlNoNetExternalEntityLoader:
4051 * @URL: the URL for the entity to load
4052 * @ID: the System ID for the entity to load
4053 * @ctxt: the context in which the entity is called or NULL
4055 * A specific entity loader disabling network accesses, though still
4056 * allowing local catalog accesses for resolution.
4058 * Returns a new allocated xmlParserInputPtr, or NULL.
4061 xmlNoNetExternalEntityLoader(const char *URL
, const char *ID
,
4062 xmlParserCtxtPtr ctxt
) {
4063 xmlParserInputPtr input
= NULL
;
4064 xmlChar
*resource
= NULL
;
4066 #ifdef LIBXML_CATALOG_ENABLED
4067 resource
= xmlResolveResourceFromCatalog(URL
, ID
, ctxt
);
4070 if (resource
== NULL
)
4071 resource
= (xmlChar
*) URL
;
4073 if (resource
!= NULL
) {
4074 if ((!xmlStrncasecmp(BAD_CAST resource
, BAD_CAST
"ftp://", 6)) ||
4075 (!xmlStrncasecmp(BAD_CAST resource
, BAD_CAST
"http://", 7))) {
4076 xmlIOErr(XML_IO_NETWORK_ATTEMPT
, (const char *) resource
);
4077 if (resource
!= (xmlChar
*) URL
)
4082 input
= xmlDefaultExternalEntityLoader((const char *) resource
, ID
, ctxt
);
4083 if (resource
!= (xmlChar
*) URL
)
4088 #define bottom_xmlIO
4089 #include "elfgcchack.h"