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
43 #if defined(_WIN32) && !defined(__CYGWIN__)
44 #define WIN32_LEAN_AND_MEAN
48 #if defined(_WIN32_WCE)
49 #include <winnls.h> /* for CP_UTF8 */
54 # define S_ISDIR(x) _S_ISDIR(x)
55 # elif defined(S_IFDIR)
57 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
58 # elif defined(_S_IFMT)
59 # define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
64 #include <libxml/xmlmemory.h>
65 #include <libxml/parser.h>
66 #include <libxml/parserInternals.h>
67 #include <libxml/xmlIO.h>
68 #include <libxml/uri.h>
69 #include <libxml/nanohttp.h>
70 #include <libxml/nanoftp.h>
71 #include <libxml/xmlerror.h>
72 #ifdef LIBXML_CATALOG_ENABLED
73 #include <libxml/catalog.h>
75 #include <libxml/globals.h>
80 /* #define VERBOSE_FAILURE */
81 /* #define DEBUG_EXTERNAL_ENTITIES */
82 /* #define DEBUG_INPUT */
91 * Input I/O callback sets
93 typedef struct _xmlInputCallback {
94 xmlInputMatchCallback matchcallback;
95 xmlInputOpenCallback opencallback;
96 xmlInputReadCallback readcallback;
97 xmlInputCloseCallback closecallback;
100 #define MAX_INPUT_CALLBACK 15
102 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
103 static int xmlInputCallbackNr = 0;
104 static int xmlInputCallbackInitialized = 0;
106 #ifdef LIBXML_OUTPUT_ENABLED
108 * Output I/O callback sets
110 typedef struct _xmlOutputCallback {
111 xmlOutputMatchCallback matchcallback;
112 xmlOutputOpenCallback opencallback;
113 xmlOutputWriteCallback writecallback;
114 xmlOutputCloseCallback closecallback;
117 #define MAX_OUTPUT_CALLBACK 15
119 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
120 static int xmlOutputCallbackNr = 0;
121 static int xmlOutputCallbackInitialized = 0;
124 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
125 #endif /* LIBXML_OUTPUT_ENABLED */
127 /************************************************************************
129 * Tree memory error handler *
131 ************************************************************************/
133 static const char *IOerr[] = {
134 "Unknown IO error", /* UNKNOWN */
135 "Permission denied", /* EACCES */
136 "Resource temporarily unavailable",/* EAGAIN */
137 "Bad file descriptor", /* EBADF */
138 "Bad message", /* EBADMSG */
139 "Resource busy", /* EBUSY */
140 "Operation canceled", /* ECANCELED */
141 "No child processes", /* ECHILD */
142 "Resource deadlock avoided",/* EDEADLK */
143 "Domain error", /* EDOM */
144 "File exists", /* EEXIST */
145 "Bad address", /* EFAULT */
146 "File too large", /* EFBIG */
147 "Operation in progress", /* EINPROGRESS */
148 "Interrupted function call",/* EINTR */
149 "Invalid argument", /* EINVAL */
150 "Input/output error", /* EIO */
151 "Is a directory", /* EISDIR */
152 "Too many open files", /* EMFILE */
153 "Too many links", /* EMLINK */
154 "Inappropriate message buffer length",/* EMSGSIZE */
155 "Filename too long", /* ENAMETOOLONG */
156 "Too many open files in system",/* ENFILE */
157 "No such device", /* ENODEV */
158 "No such file or directory",/* ENOENT */
159 "Exec format error", /* ENOEXEC */
160 "No locks available", /* ENOLCK */
161 "Not enough space", /* ENOMEM */
162 "No space left on device", /* ENOSPC */
163 "Function not implemented", /* ENOSYS */
164 "Not a directory", /* ENOTDIR */
165 "Directory not empty", /* ENOTEMPTY */
166 "Not supported", /* ENOTSUP */
167 "Inappropriate I/O control operation",/* ENOTTY */
168 "No such device or address",/* ENXIO */
169 "Operation not permitted", /* EPERM */
170 "Broken pipe", /* EPIPE */
171 "Result too large", /* ERANGE */
172 "Read-only file system", /* EROFS */
173 "Invalid seek", /* ESPIPE */
174 "No such process", /* ESRCH */
175 "Operation timed out", /* ETIMEDOUT */
176 "Improper link", /* EXDEV */
177 "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
178 "encoder error", /* XML_IO_ENCODER */
184 "not a socket", /* ENOTSOCK */
185 "already connected", /* EISCONN */
186 "connection refused", /* ECONNREFUSED */
187 "unreachable network", /* ENETUNREACH */
188 "adddress in use", /* EADDRINUSE */
189 "already in use", /* EALREADY */
190 "unknown address familly", /* EAFNOSUPPORT */
193 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
195 * __xmlIOWin32UTF8ToWChar:
196 * @u8String: uft-8 string
198 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
201 __xmlIOWin32UTF8ToWChar(const char *u8String)
203 wchar_t *wString = NULL;
207 MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
210 wString = xmlMalloc(wLen * sizeof(wchar_t));
212 if (MultiByteToWideChar
213 (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
227 * @extra: extra informations
229 * Handle an out of memory condition
232 xmlIOErrMemory(const char *extra)
234 __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
239 * @code: the error number
241 * @extra: extra informations
243 * Handle an I/O error
246 __xmlIOErr(int domain, int code, const char *extra)
252 if (errno == 0) code = 0;
254 else if (errno == EACCES) code = XML_IO_EACCES;
257 else if (errno == EAGAIN) code = XML_IO_EAGAIN;
260 else if (errno == EBADF) code = XML_IO_EBADF;
263 else if (errno == EBADMSG) code = XML_IO_EBADMSG;
266 else if (errno == EBUSY) code = XML_IO_EBUSY;
269 else if (errno == ECANCELED) code = XML_IO_ECANCELED;
272 else if (errno == ECHILD) code = XML_IO_ECHILD;
275 else if (errno == EDEADLK) code = XML_IO_EDEADLK;
278 else if (errno == EDOM) code = XML_IO_EDOM;
281 else if (errno == EEXIST) code = XML_IO_EEXIST;
284 else if (errno == EFAULT) code = XML_IO_EFAULT;
287 else if (errno == EFBIG) code = XML_IO_EFBIG;
290 else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
293 else if (errno == EINTR) code = XML_IO_EINTR;
296 else if (errno == EINVAL) code = XML_IO_EINVAL;
299 else if (errno == EIO) code = XML_IO_EIO;
302 else if (errno == EISDIR) code = XML_IO_EISDIR;
305 else if (errno == EMFILE) code = XML_IO_EMFILE;
308 else if (errno == EMLINK) code = XML_IO_EMLINK;
311 else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
314 else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
317 else if (errno == ENFILE) code = XML_IO_ENFILE;
320 else if (errno == ENODEV) code = XML_IO_ENODEV;
323 else if (errno == ENOENT) code = XML_IO_ENOENT;
326 else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
329 else if (errno == ENOLCK) code = XML_IO_ENOLCK;
332 else if (errno == ENOMEM) code = XML_IO_ENOMEM;
335 else if (errno == ENOSPC) code = XML_IO_ENOSPC;
338 else if (errno == ENOSYS) code = XML_IO_ENOSYS;
341 else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
344 else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
347 else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
350 else if (errno == ENOTTY) code = XML_IO_ENOTTY;
353 else if (errno == ENXIO) code = XML_IO_ENXIO;
356 else if (errno == EPERM) code = XML_IO_EPERM;
359 else if (errno == EPIPE) code = XML_IO_EPIPE;
362 else if (errno == ERANGE) code = XML_IO_ERANGE;
365 else if (errno == EROFS) code = XML_IO_EROFS;
368 else if (errno == ESPIPE) code = XML_IO_ESPIPE;
371 else if (errno == ESRCH) code = XML_IO_ESRCH;
374 else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
377 else if (errno == EXDEV) code = XML_IO_EXDEV;
380 else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
383 else if (errno == EISCONN) code = XML_IO_EISCONN;
386 else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
389 else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
392 else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
395 else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
398 else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
401 else if (errno == EALREADY) code = XML_IO_EALREADY;
404 else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
406 else code = XML_IO_UNKNOWN;
407 #endif /* HAVE_ERRNO_H */
410 if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
411 if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
413 __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
418 * @code: the error number
419 * @extra: extra informations
421 * Handle an I/O error
424 xmlIOErr(int code, const char *extra)
426 __xmlIOErr(XML_FROM_IO, code, extra);
431 * @ctx: the parser context
432 * @extra: extra informations
434 * Handle a resource access error
437 __xmlLoaderErr(void *ctx, const char *msg, const char *filename)
439 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
440 xmlStructuredErrorFunc schannel = NULL;
441 xmlGenericErrorFunc channel = NULL;
443 xmlErrorLevel level = XML_ERR_ERROR;
445 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
446 (ctxt->instate == XML_PARSER_EOF))
448 if ((ctxt != NULL) && (ctxt->sax != NULL)) {
449 if (ctxt->validate) {
450 channel = ctxt->sax->error;
451 level = XML_ERR_ERROR;
453 channel = ctxt->sax->warning;
454 level = XML_ERR_WARNING;
456 if (ctxt->sax->initialized == XML_SAX2_MAGIC)
457 schannel = ctxt->sax->serror;
458 data = ctxt->userData;
460 __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
461 XML_IO_LOAD_ERROR, level, NULL, 0,
462 filename, NULL, NULL, 0, 0,
467 /************************************************************************
469 * Tree memory error handler *
471 ************************************************************************/
473 * xmlNormalizeWindowsPath:
474 * @path: the input file path
476 * This function is obsolete. Please see xmlURIFromPath in uri.c for
479 * Returns a canonicalized version of the path
482 xmlNormalizeWindowsPath(const xmlChar *path)
484 return xmlCanonicPath(path);
488 * xmlCleanupInputCallbacks:
490 * clears the entire input callback table. this includes the
494 xmlCleanupInputCallbacks(void)
498 if (!xmlInputCallbackInitialized)
501 for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
502 xmlInputCallbackTable[i].matchcallback = NULL;
503 xmlInputCallbackTable[i].opencallback = NULL;
504 xmlInputCallbackTable[i].readcallback = NULL;
505 xmlInputCallbackTable[i].closecallback = NULL;
508 xmlInputCallbackNr = 0;
509 xmlInputCallbackInitialized = 0;
513 * xmlPopInputCallbacks:
515 * Clear the top input callback from the input stack. this includes the
518 * Returns the number of input callback registered or -1 in case of error.
521 xmlPopInputCallbacks(void)
523 if (!xmlInputCallbackInitialized)
526 if (xmlInputCallbackNr <= 0)
529 xmlInputCallbackNr--;
530 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
531 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
532 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
533 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
535 return(xmlInputCallbackNr);
538 #ifdef LIBXML_OUTPUT_ENABLED
540 * xmlCleanupOutputCallbacks:
542 * clears the entire output callback table. this includes the
543 * compiled-in I/O callbacks.
546 xmlCleanupOutputCallbacks(void)
550 if (!xmlOutputCallbackInitialized)
553 for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
554 xmlOutputCallbackTable[i].matchcallback = NULL;
555 xmlOutputCallbackTable[i].opencallback = NULL;
556 xmlOutputCallbackTable[i].writecallback = NULL;
557 xmlOutputCallbackTable[i].closecallback = NULL;
560 xmlOutputCallbackNr = 0;
561 xmlOutputCallbackInitialized = 0;
563 #endif /* LIBXML_OUTPUT_ENABLED */
565 /************************************************************************
567 * Standard I/O for file accesses *
569 ************************************************************************/
571 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
575 * @path: the path in utf-8 encoding
576 * @mode: type of access (0 - read, 1 - write)
578 * function opens the file specified by @path
582 xmlWrapOpenUtf8(const char *path,int mode)
587 wPath = __xmlIOWin32UTF8ToWChar(path);
590 fd = _wfopen(wPath, mode ? L"wb" : L"rb");
593 /* maybe path in native encoding */
595 fd = fopen(path, mode ? "wb" : "rb");
602 xmlWrapGzOpenUtf8(const char *path, const char *mode)
607 fd = gzopen (path, mode);
611 wPath = __xmlIOWin32UTF8ToWChar(path);
614 int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
616 m |= (strstr(mode, "b") ? _O_BINARY : 0);
618 d = _wopen(wPath, m);
620 fd = gzdopen(d, mode);
630 * @path: the path in utf-8 encoding
631 * @info: structure that stores results
633 * function obtains information about the file or directory
637 xmlWrapStatUtf8(const char *path, struct _stat *info) {
641 wPath = __xmlIOWin32UTF8ToWChar(path);
643 retval = _wstat(wPath, info);
646 /* maybe path in native encoding */
648 retval = _stat(path, info);
656 * @path: the path to check
658 * function checks to see if @path is a valid source
659 * (file, socket...) for XML.
661 * if stat is not available on the target machine,
662 * returns 1. if stat fails, returns 0 (if calling
663 * stat on the filename fails, it can't be right).
664 * if stat succeeds and the file is a directory,
665 * returns 2. otherwise returns 1.
669 xmlCheckFilename (const char *path)
672 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
673 struct _stat stat_buffer;
675 struct stat stat_buffer;
682 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
684 * On Windows stat and wstat do not work with long pathname,
685 * which start with '\\?\'
687 if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
691 if (xmlWrapStatUtf8(path, &stat_buffer) == -1)
694 if (stat(path, &stat_buffer) == -1)
698 if (S_ISDIR(stat_buffer.st_mode))
701 #endif /* HAVE_STAT */
708 * No Operation function, does nothing, no input
719 * @context: the I/O context
720 * @buffer: where to drop data
721 * @len: number of bytes to read
723 * Read @len bytes to @buffer from the I/O channel.
725 * Returns the number of bytes written
728 xmlFdRead (void * context, char * buffer, int len) {
731 ret = read((int) (ptrdiff_t) context, &buffer[0], len);
732 if (ret < 0) xmlIOErr(0, "read()");
736 #ifdef LIBXML_OUTPUT_ENABLED
739 * @context: the I/O context
740 * @buffer: where to get data
741 * @len: number of bytes to write
743 * Write @len bytes from @buffer to the I/O channel.
745 * Returns the number of bytes written
748 xmlFdWrite (void * context, const char * buffer, int len) {
752 ret = write((int) (ptrdiff_t) context, &buffer[0], len);
753 if (ret < 0) xmlIOErr(0, "write()");
757 #endif /* LIBXML_OUTPUT_ENABLED */
761 * @context: the I/O context
763 * Close an I/O channel
765 * Returns 0 in case of success and error code otherwise
768 xmlFdClose (void * context) {
770 ret = close((int) (ptrdiff_t) context);
771 if (ret < 0) xmlIOErr(0, "close()");
777 * @filename: the URI for matching
781 * Returns 1 if matches, 0 otherwise
784 xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
790 * @filename: the URI for matching
792 * input from FILE *, supports compressed input
793 * if @filename is " " then the standard input is used
795 * Returns an I/O context or NULL in case of error
798 xmlFileOpen_real (const char *filename) {
799 const char *path = filename;
802 if (filename == NULL)
805 if (!strcmp(filename, "-")) {
810 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
811 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
812 path = &filename[17];
814 path = &filename[16];
816 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
817 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
822 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
823 /* lots of generators seems to lazy to read RFC 1738 */
824 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
831 /* Do not check DDNAME on zOS ! */
832 #if !defined(__MVS__)
833 if (!xmlCheckFilename(path))
837 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
838 fd = xmlWrapOpenUtf8(path, 0);
840 fd = fopen(path, "r");
842 if (fd == NULL) xmlIOErr(0, path);
848 * @filename: the URI for matching
850 * Wrapper around xmlFileOpen_real that try it with an unescaped
851 * version of @filename, if this fails fallback to @filename
853 * Returns a handler or NULL in case or failure
856 xmlFileOpen (const char *filename) {
860 retval = xmlFileOpen_real(filename);
861 if (retval == NULL) {
862 unescaped = xmlURIUnescapeString(filename, 0, NULL);
863 if (unescaped != NULL) {
864 retval = xmlFileOpen_real(unescaped);
872 #ifdef LIBXML_OUTPUT_ENABLED
875 * @filename: the URI for matching
877 * output to from FILE *,
878 * if @filename is "-" then the standard output is used
880 * Returns an I/O context or NULL in case of error
883 xmlFileOpenW (const char *filename) {
884 const char *path = NULL;
887 if (!strcmp(filename, "-")) {
892 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
893 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
894 path = &filename[17];
896 path = &filename[16];
898 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
899 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
910 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
911 fd = xmlWrapOpenUtf8(path, 1);
913 fd = fopen(path, "w");
915 fd = fopen(path, "wb");
918 if (fd == NULL) xmlIOErr(0, path);
921 #endif /* LIBXML_OUTPUT_ENABLED */
925 * @context: the I/O context
926 * @buffer: where to drop data
927 * @len: number of bytes to write
929 * Read @len bytes to @buffer from the I/O channel.
931 * Returns the number of bytes written or < 0 in case of failure
934 xmlFileRead (void * context, char * buffer, int len) {
936 if ((context == NULL) || (buffer == NULL))
938 ret = fread(&buffer[0], 1, len, (FILE *) context);
939 if (ret < 0) xmlIOErr(0, "fread()");
943 #ifdef LIBXML_OUTPUT_ENABLED
946 * @context: the I/O context
947 * @buffer: where to drop data
948 * @len: number of bytes to write
950 * Write @len bytes from @buffer to the I/O channel.
952 * Returns the number of bytes written
955 xmlFileWrite (void * context, const char * buffer, int len) {
958 if ((context == NULL) || (buffer == NULL))
960 items = fwrite(&buffer[0], len, 1, (FILE *) context);
961 if ((items == 0) && (ferror((FILE *) context))) {
962 xmlIOErr(0, "fwrite()");
967 #endif /* LIBXML_OUTPUT_ENABLED */
971 * @context: the I/O context
973 * Close an I/O channel
975 * Returns 0 or -1 in case of error
978 xmlFileClose (void * context) {
984 fil = (FILE *) context;
985 if ((fil == stdout) || (fil == stderr)) {
988 xmlIOErr(0, "fflush()");
993 ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
995 xmlIOErr(0, "fclose()");
1001 * @context: the I/O context
1003 * Flush an I/O channel
1006 xmlFileFlush (void * context) {
1009 if (context == NULL)
1011 ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
1013 xmlIOErr(0, "fflush()");
1017 #ifdef LIBXML_OUTPUT_ENABLED
1020 * @context: the xmlBuffer
1021 * @buffer: the data to write
1022 * @len: number of bytes to write
1024 * Write @len bytes from @buffer to the xml buffer
1026 * Returns the number of bytes written
1029 xmlBufferWrite (void * context, const char * buffer, int len) {
1032 ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
1040 /************************************************************************
1042 * I/O for compressed file accesses *
1044 ************************************************************************/
1047 * @filename: the URI for matching
1049 * input from compressed file test
1051 * Returns 1 if matches, 0 otherwise
1054 xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
1059 * xmlGzfileOpen_real:
1060 * @filename: the URI for matching
1062 * input from compressed file open
1063 * if @filename is " " then the standard input is used
1065 * Returns an I/O context or NULL in case of error
1068 xmlGzfileOpen_real (const char *filename) {
1069 const char *path = NULL;
1072 if (!strcmp(filename, "-")) {
1073 int duped_fd = dup(fileno(stdin));
1074 fd = gzdopen(duped_fd, "rb");
1075 if (fd == Z_NULL && duped_fd >= 0) {
1076 close(duped_fd); /* gzdOpen() does not close on failure */
1079 return((void *) fd);
1082 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
1083 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1084 path = &filename[17];
1086 path = &filename[16];
1088 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1089 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1090 path = &filename[8];
1092 path = &filename[7];
1099 if (!xmlCheckFilename(path))
1102 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1103 fd = xmlWrapGzOpenUtf8(path, "rb");
1105 fd = gzopen(path, "rb");
1107 return((void *) fd);
1112 * @filename: the URI for matching
1114 * Wrapper around xmlGzfileOpen if the open fais, it will
1115 * try to unescape @filename
1118 xmlGzfileOpen (const char *filename) {
1122 retval = xmlGzfileOpen_real(filename);
1123 if (retval == NULL) {
1124 unescaped = xmlURIUnescapeString(filename, 0, NULL);
1125 if (unescaped != NULL) {
1126 retval = xmlGzfileOpen_real(unescaped);
1133 #ifdef LIBXML_OUTPUT_ENABLED
1136 * @filename: the URI for matching
1137 * @compression: the compression factor (0 - 9 included)
1139 * input from compressed file open
1140 * if @filename is " " then the standard input is used
1142 * Returns an I/O context or NULL in case of error
1145 xmlGzfileOpenW (const char *filename, int compression) {
1146 const char *path = NULL;
1150 snprintf(mode, sizeof(mode), "wb%d", compression);
1151 if (!strcmp(filename, "-")) {
1152 int duped_fd = dup(fileno(stdout));
1153 fd = gzdopen(duped_fd, "rb");
1154 if (fd == Z_NULL && duped_fd >= 0) {
1155 close(duped_fd); /* gzdOpen() does not close on failure */
1158 return((void *) fd);
1161 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
1162 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1163 path = &filename[17];
1165 path = &filename[16];
1167 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1168 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1169 path = &filename[8];
1171 path = &filename[7];
1179 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1180 fd = xmlWrapGzOpenUtf8(path, mode);
1182 fd = gzopen(path, mode);
1184 return((void *) fd);
1186 #endif /* LIBXML_OUTPUT_ENABLED */
1190 * @context: the I/O context
1191 * @buffer: where to drop data
1192 * @len: number of bytes to write
1194 * Read @len bytes to @buffer from the compressed I/O channel.
1196 * Returns the number of bytes read.
1199 xmlGzfileRead (void * context, char * buffer, int len) {
1202 ret = gzread((gzFile) context, &buffer[0], len);
1203 if (ret < 0) xmlIOErr(0, "gzread()");
1207 #ifdef LIBXML_OUTPUT_ENABLED
1210 * @context: the I/O context
1211 * @buffer: where to drop data
1212 * @len: number of bytes to write
1214 * Write @len bytes from @buffer to the compressed I/O channel.
1216 * Returns the number of bytes written
1219 xmlGzfileWrite (void * context, const char * buffer, int len) {
1222 ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
1223 if (ret < 0) xmlIOErr(0, "gzwrite()");
1226 #endif /* LIBXML_OUTPUT_ENABLED */
1230 * @context: the I/O context
1232 * Close a compressed I/O channel
1235 xmlGzfileClose (void * context) {
1238 ret = (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
1239 if (ret < 0) xmlIOErr(0, "gzclose()");
1242 #endif /* HAVE_ZLIB_H */
1244 #ifdef LIBXML_LZMA_ENABLED
1245 /************************************************************************
1247 * I/O for compressed file accesses *
1249 ************************************************************************/
1253 * @filename: the URI for matching
1255 * input from compressed file test
1257 * Returns 1 if matches, 0 otherwise
1260 xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
1265 * xmlXzFileOpen_real:
1266 * @filename: the URI for matching
1268 * input from compressed file open
1269 * if @filename is " " then the standard input is used
1271 * Returns an I/O context or NULL in case of error
1274 xmlXzfileOpen_real (const char *filename) {
1275 const char *path = NULL;
1278 if (!strcmp(filename, "-")) {
1279 fd = __libxml2_xzdopen(dup(fileno(stdin)), "rb");
1280 return((void *) fd);
1283 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
1284 path = &filename[16];
1285 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1286 path = &filename[7];
1287 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
1288 /* lots of generators seems to lazy to read RFC 1738 */
1289 path = &filename[5];
1295 if (!xmlCheckFilename(path))
1298 fd = __libxml2_xzopen(path, "rb");
1299 return((void *) fd);
1304 * @filename: the URI for matching
1306 * Wrapper around xmlXzfileOpen_real that try it with an unescaped
1307 * version of @filename, if this fails fallback to @filename
1309 * Returns a handler or NULL in case or failure
1312 xmlXzfileOpen (const char *filename) {
1316 retval = xmlXzfileOpen_real(filename);
1317 if (retval == NULL) {
1318 unescaped = xmlURIUnescapeString(filename, 0, NULL);
1319 if (unescaped != NULL) {
1320 retval = xmlXzfileOpen_real(unescaped);
1330 * @context: the I/O context
1331 * @buffer: where to drop data
1332 * @len: number of bytes to write
1334 * Read @len bytes to @buffer from the compressed I/O channel.
1336 * Returns the number of bytes written
1339 xmlXzfileRead (void * context, char * buffer, int len) {
1342 ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
1343 if (ret < 0) xmlIOErr(0, "xzread()");
1349 * @context: the I/O context
1351 * Close a compressed I/O channel
1354 xmlXzfileClose (void * context) {
1357 ret = (__libxml2_xzclose((xzFile) context) == LZMA_OK ) ? 0 : -1;
1358 if (ret < 0) xmlIOErr(0, "xzclose()");
1361 #endif /* LIBXML_LZMA_ENABLED */
1363 #ifdef LIBXML_HTTP_ENABLED
1364 /************************************************************************
1366 * I/O for HTTP file accesses *
1368 ************************************************************************/
1370 #ifdef LIBXML_OUTPUT_ENABLED
1371 typedef struct xmlIOHTTPWriteCtxt_
1379 } xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
1383 #define DFLT_WBITS ( -15 )
1384 #define DFLT_MEM_LVL ( 8 )
1385 #define GZ_MAGIC1 ( 0x1f )
1386 #define GZ_MAGIC2 ( 0x8b )
1387 #define LXML_ZLIB_OS_CODE ( 0x03 )
1388 #define INIT_HTTP_BUFF_SIZE ( 32768 )
1389 #define DFLT_ZLIB_RATIO ( 5 )
1392 ** Data structure and functions to work with sending compressed data
1396 typedef struct xmlZMemBuff_
1401 unsigned char * zbuff;
1404 } xmlZMemBuff, *xmlZMemBuffPtr;
1407 * append_reverse_ulong
1408 * @buff: Compressed memory buffer
1409 * @data: Unsigned long to append
1411 * Append a unsigned long in reverse byte order to the end of the
1415 append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
1423 ** This is plagiarized from putLong in gzio.c (zlib source) where
1424 ** the number "4" is hardcoded. If zlib is ever patched to
1425 ** support 64 bit file sizes, this code would need to be patched
1429 for ( idx = 0; idx < 4; idx++ ) {
1430 *buff->zctrl.next_out = ( data & 0xff );
1432 buff->zctrl.next_out++;
1441 * @buff: The memory buffer context to clear
1443 * Release all the resources associated with the compressed memory buffer.
1446 xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
1455 xmlFree( buff->zbuff );
1457 z_err = deflateEnd( &buff->zctrl );
1458 if ( z_err != Z_OK )
1459 xmlGenericError( xmlGenericErrorContext,
1460 "xmlFreeZMemBuff: Error releasing zlib context: %d\n",
1463 deflateEnd( &buff->zctrl );
1472 *@compression: Compression value to use
1474 * Create a memory buffer to hold the compressed XML document. The
1475 * compressed document in memory will end up being identical to what
1476 * would be created if gzopen/gzwrite/gzclose were being used to
1477 * write the document to disk. The code for the header/trailer data to
1478 * the compression is plagiarized from the zlib source files.
1481 xmlCreateZMemBuff( int compression ) {
1485 xmlZMemBuffPtr buff = NULL;
1487 if ( ( compression < 1 ) || ( compression > 9 ) )
1490 /* Create the control and data areas */
1492 buff = xmlMalloc( sizeof( xmlZMemBuff ) );
1493 if ( buff == NULL ) {
1494 xmlIOErrMemory("creating buffer context");
1498 (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
1499 buff->size = INIT_HTTP_BUFF_SIZE;
1500 buff->zbuff = xmlMalloc( buff->size );
1501 if ( buff->zbuff == NULL ) {
1502 xmlFreeZMemBuff( buff );
1503 xmlIOErrMemory("creating buffer");
1507 z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
1508 DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
1509 if ( z_err != Z_OK ) {
1511 xmlFreeZMemBuff( buff );
1513 xmlStrPrintf(msg, 500,
1514 "xmlCreateZMemBuff: %s %d\n",
1515 "Error initializing compression context. ZLIB error:",
1517 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1521 /* Set the header data. The CRC will be needed for the trailer */
1522 buff->crc = crc32( 0L, NULL, 0 );
1523 hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
1524 "%c%c%c%c%c%c%c%c%c%c",
1525 GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
1526 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
1527 buff->zctrl.next_out = buff->zbuff + hdr_lgth;
1528 buff->zctrl.avail_out = buff->size - hdr_lgth;
1535 * @buff: Buffer used to compress and consolidate data.
1536 * @ext_amt: Number of bytes to extend the buffer.
1538 * Extend the internal buffer used to store the compressed data by the
1541 * Returns 0 on success or -1 on failure to extend the buffer. On failure
1542 * the original buffer still exists at the original size.
1545 xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
1551 unsigned char * tmp_ptr = NULL;
1556 else if ( ext_amt == 0 )
1559 cur_used = buff->zctrl.next_out - buff->zbuff;
1560 new_size = buff->size + ext_amt;
1563 if ( cur_used > new_size )
1564 xmlGenericError( xmlGenericErrorContext,
1565 "xmlZMemBuffExtend: %s\n%s %d bytes.\n",
1566 "Buffer overwrite detected during compressed memory",
1567 "buffer extension. Overflowed by",
1568 (cur_used - new_size ) );
1571 tmp_ptr = xmlRealloc( buff->zbuff, new_size );
1572 if ( tmp_ptr != NULL ) {
1574 buff->size = new_size;
1575 buff->zbuff = tmp_ptr;
1576 buff->zctrl.next_out = tmp_ptr + cur_used;
1577 buff->zctrl.avail_out = new_size - cur_used;
1581 xmlStrPrintf(msg, 500,
1582 "xmlZMemBuffExtend: %s %lu bytes.\n",
1583 "Allocation failure extending output buffer to",
1584 (unsigned long) new_size );
1585 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1593 * @buff: Buffer used to compress and consolidate data
1594 * @src: Uncompressed source content to append to buffer
1595 * @len: Length of source data to append to buffer
1597 * Compress and append data to the internal buffer. The data buffer
1598 * will be expanded if needed to store the additional data.
1600 * Returns the number of bytes appended to the buffer or -1 on error.
1603 xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
1608 if ( ( buff == NULL ) || ( src == NULL ) )
1611 buff->zctrl.avail_in = len;
1612 buff->zctrl.next_in = (unsigned char *)src;
1613 while ( buff->zctrl.avail_in > 0 ) {
1615 ** Extend the buffer prior to deflate call if a reasonable amount
1616 ** of output buffer space is not available.
1618 min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
1619 if ( buff->zctrl.avail_out <= min_accept ) {
1620 if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1624 z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
1625 if ( z_err != Z_OK ) {
1627 xmlStrPrintf(msg, 500,
1628 "xmlZMemBuffAppend: %s %d %s - %d",
1629 "Compression error while appending",
1630 len, "bytes to buffer. ZLIB error", z_err );
1631 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1636 buff->crc = crc32( buff->crc, (unsigned char *)src, len );
1642 * xmlZMemBuffGetContent
1643 * @buff: Compressed memory content buffer
1644 * @data_ref: Pointer reference to point to compressed content
1646 * Flushes the compression buffers, appends gzip file trailers and
1647 * returns the compressed content and length of the compressed data.
1648 * NOTE: The gzip trailer code here is plagiarized from zlib source.
1650 * Returns the length of the compressed data or -1 on error.
1653 xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
1658 if ( ( buff == NULL ) || ( data_ref == NULL ) )
1661 /* Need to loop until compression output buffers are flushed */
1665 z_err = deflate( &buff->zctrl, Z_FINISH );
1666 if ( z_err == Z_OK ) {
1667 /* In this case Z_OK means more buffer space needed */
1669 if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1673 while ( z_err == Z_OK );
1675 /* If the compression state is not Z_STREAM_END, some error occurred */
1677 if ( z_err == Z_STREAM_END ) {
1679 /* Need to append the gzip data trailer */
1681 if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
1682 if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
1687 ** For whatever reason, the CRC and length data are pushed out
1688 ** in reverse byte order. So a memcpy can't be used here.
1691 append_reverse_ulong( buff, buff->crc );
1692 append_reverse_ulong( buff, buff->zctrl.total_in );
1694 zlgth = buff->zctrl.next_out - buff->zbuff;
1695 *data_ref = (char *)buff->zbuff;
1700 xmlStrPrintf(msg, 500,
1701 "xmlZMemBuffGetContent: %s - %d\n",
1702 "Error flushing zlib buffers. Error code", z_err );
1703 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1708 #endif /* LIBXML_OUTPUT_ENABLED */
1709 #endif /* HAVE_ZLIB_H */
1711 #ifdef LIBXML_OUTPUT_ENABLED
1713 * xmlFreeHTTPWriteCtxt
1714 * @ctxt: Context to cleanup
1716 * Free allocated memory and reclaim system resources.
1721 xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
1723 if ( ctxt->uri != NULL )
1724 xmlFree( ctxt->uri );
1726 if ( ctxt->doc_buff != NULL ) {
1729 if ( ctxt->compression > 0 ) {
1730 xmlFreeZMemBuff( ctxt->doc_buff );
1735 xmlOutputBufferClose( ctxt->doc_buff );
1742 #endif /* LIBXML_OUTPUT_ENABLED */
1747 * @filename: the URI for matching
1749 * check if the URI matches an HTTP one
1751 * Returns 1 if matches, 0 otherwise
1754 xmlIOHTTPMatch (const char *filename) {
1755 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
1762 * @filename: the URI for matching
1764 * open an HTTP I/O channel
1766 * Returns an I/O context or NULL in case of error
1769 xmlIOHTTPOpen (const char *filename) {
1770 return(xmlNanoHTTPOpen(filename, NULL));
1773 #ifdef LIBXML_OUTPUT_ENABLED
1776 * @post_uri: The destination URI for the document
1777 * @compression: The compression desired for the document.
1779 * Open a temporary buffer to collect the document for a subsequent HTTP POST
1780 * request. Non-static as is called from the output buffer creation routine.
1782 * Returns an I/O context or NULL in case of error.
1786 xmlIOHTTPOpenW(const char *post_uri, int compression ATTRIBUTE_UNUSED)
1789 xmlIOHTTPWriteCtxtPtr ctxt = NULL;
1791 if (post_uri == NULL)
1794 ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
1796 xmlIOErrMemory("creating HTTP output context");
1800 (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
1802 ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
1803 if (ctxt->uri == NULL) {
1804 xmlIOErrMemory("copying URI");
1805 xmlFreeHTTPWriteCtxt(ctxt);
1810 * ** Since the document length is required for an HTTP post,
1811 * ** need to put the document into a buffer. A memory buffer
1812 * ** is being used to avoid pushing the data to disk and back.
1816 if ((compression > 0) && (compression <= 9)) {
1818 ctxt->compression = compression;
1819 ctxt->doc_buff = xmlCreateZMemBuff(compression);
1823 /* Any character conversions should have been done before this */
1825 ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
1828 if (ctxt->doc_buff == NULL) {
1829 xmlFreeHTTPWriteCtxt(ctxt);
1835 #endif /* LIBXML_OUTPUT_ENABLED */
1837 #ifdef LIBXML_OUTPUT_ENABLED
1839 * xmlIOHTTPDfltOpenW
1840 * @post_uri: The destination URI for this document.
1842 * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
1843 * HTTP post command. This function should generally not be used as
1844 * the open callback is short circuited in xmlOutputBufferCreateFile.
1846 * Returns a pointer to the new IO context.
1849 xmlIOHTTPDfltOpenW( const char * post_uri ) {
1850 return ( xmlIOHTTPOpenW( post_uri, 0 ) );
1852 #endif /* LIBXML_OUTPUT_ENABLED */
1856 * @context: the I/O context
1857 * @buffer: where to drop data
1858 * @len: number of bytes to write
1860 * Read @len bytes to @buffer from the I/O channel.
1862 * Returns the number of bytes written
1865 xmlIOHTTPRead(void * context, char * buffer, int len) {
1866 if ((buffer == NULL) || (len < 0)) return(-1);
1867 return(xmlNanoHTTPRead(context, &buffer[0], len));
1870 #ifdef LIBXML_OUTPUT_ENABLED
1873 * @context: previously opened writing context
1874 * @buffer: data to output to temporary buffer
1875 * @len: bytes to output
1877 * Collect data from memory buffer into a temporary file for later
1880 * Returns number of bytes written.
1884 xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
1886 xmlIOHTTPWriteCtxtPtr ctxt = context;
1888 if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
1893 /* Use gzwrite or fwrite as previously setup in the open call */
1896 if ( ctxt->compression > 0 )
1897 len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
1901 len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
1905 xmlStrPrintf(msg, 500,
1906 "xmlIOHTTPWrite: %s\n%s '%s'.\n",
1907 "Error appending to internal buffer.",
1908 "Error sending document to URI",
1910 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1916 #endif /* LIBXML_OUTPUT_ENABLED */
1921 * @context: the I/O context
1923 * Close an HTTP I/O channel
1928 xmlIOHTTPClose (void * context) {
1929 xmlNanoHTTPClose(context);
1933 #ifdef LIBXML_OUTPUT_ENABLED
1935 * xmlIOHTTCloseWrite
1936 * @context: The I/O context
1937 * @http_mthd: The HTTP method to be used when sending the data
1939 * Close the transmit HTTP I/O channel and actually send the data.
1942 xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
1946 int content_lgth = 0;
1947 xmlIOHTTPWriteCtxtPtr ctxt = context;
1949 char * http_content = NULL;
1950 char * content_encoding = NULL;
1951 char * content_type = (char *) "text/xml";
1952 void * http_ctxt = NULL;
1954 if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
1957 /* Retrieve the content from the appropriate buffer */
1961 if ( ctxt->compression > 0 ) {
1962 content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
1963 content_encoding = (char *) "Content-Encoding: gzip";
1968 /* Pull the data out of the memory output buffer */
1970 xmlOutputBufferPtr dctxt = ctxt->doc_buff;
1971 http_content = (char *) xmlBufContent(dctxt->buffer);
1972 content_lgth = xmlBufUse(dctxt->buffer);
1975 if ( http_content == NULL ) {
1977 xmlStrPrintf(msg, 500,
1978 "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
1979 "Error retrieving content.\nUnable to",
1980 http_mthd, "data to URI", ctxt->uri );
1981 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1986 http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
1987 &content_type, content_encoding,
1990 if ( http_ctxt != NULL ) {
1992 /* If testing/debugging - dump reply with request content */
1994 FILE * tst_file = NULL;
1995 char buffer[ 4096 ];
1996 char * dump_name = NULL;
1999 xmlGenericError( xmlGenericErrorContext,
2000 "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n",
2001 http_mthd, ctxt->uri,
2002 xmlNanoHTTPReturnCode( http_ctxt ) );
2005 ** Since either content or reply may be gzipped,
2006 ** dump them to separate files instead of the
2007 ** standard error context.
2010 dump_name = tempnam( NULL, "lxml" );
2011 if ( dump_name != NULL ) {
2012 (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
2014 tst_file = fopen( buffer, "wb" );
2015 if ( tst_file != NULL ) {
2016 xmlGenericError( xmlGenericErrorContext,
2017 "Transmitted content saved in file: %s\n", buffer );
2019 fwrite( http_content, sizeof( char ),
2020 content_lgth, tst_file );
2024 (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
2025 tst_file = fopen( buffer, "wb" );
2026 if ( tst_file != NULL ) {
2027 xmlGenericError( xmlGenericErrorContext,
2028 "Reply content saved in file: %s\n", buffer );
2031 while ( (avail = xmlNanoHTTPRead( http_ctxt,
2032 buffer, sizeof( buffer ) )) > 0 ) {
2034 fwrite( buffer, sizeof( char ), avail, tst_file );
2042 #endif /* DEBUG_HTTP */
2044 http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
2045 if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
2049 xmlStrPrintf(msg, 500,
2050 "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
2051 http_mthd, content_lgth,
2052 "bytes to URI", ctxt->uri,
2053 "failed. HTTP return code:", http_rtn );
2054 xmlIOErr(XML_IO_WRITE, (const char *) msg);
2057 xmlNanoHTTPClose( http_ctxt );
2058 xmlFree( content_type );
2062 /* Final cleanups */
2064 xmlFreeHTTPWriteCtxt( ctxt );
2066 return ( close_rc );
2072 * @context: The I/O context
2074 * Close the transmit HTTP I/O channel and actually send data using a PUT
2078 xmlIOHTTPClosePut( void * ctxt ) {
2079 return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
2084 * xmlIOHTTPClosePost
2086 * @context: The I/O context
2088 * Close the transmit HTTP I/O channel and actually send data using a POST
2092 xmlIOHTTPClosePost( void * ctxt ) {
2093 return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
2095 #endif /* LIBXML_OUTPUT_ENABLED */
2097 #endif /* LIBXML_HTTP_ENABLED */
2099 #ifdef LIBXML_FTP_ENABLED
2100 /************************************************************************
2102 * I/O for FTP file accesses *
2104 ************************************************************************/
2107 * @filename: the URI for matching
2109 * check if the URI matches an FTP one
2111 * Returns 1 if matches, 0 otherwise
2114 xmlIOFTPMatch (const char *filename) {
2115 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
2122 * @filename: the URI for matching
2124 * open an FTP I/O channel
2126 * Returns an I/O context or NULL in case of error
2129 xmlIOFTPOpen (const char *filename) {
2130 return(xmlNanoFTPOpen(filename));
2135 * @context: the I/O context
2136 * @buffer: where to drop data
2137 * @len: number of bytes to write
2139 * Read @len bytes to @buffer from the I/O channel.
2141 * Returns the number of bytes written
2144 xmlIOFTPRead(void * context, char * buffer, int len) {
2145 if ((buffer == NULL) || (len < 0)) return(-1);
2146 return(xmlNanoFTPRead(context, &buffer[0], len));
2151 * @context: the I/O context
2153 * Close an FTP I/O channel
2158 xmlIOFTPClose (void * context) {
2159 return ( xmlNanoFTPClose(context) );
2161 #endif /* LIBXML_FTP_ENABLED */
2165 * xmlRegisterInputCallbacks:
2166 * @matchFunc: the xmlInputMatchCallback
2167 * @openFunc: the xmlInputOpenCallback
2168 * @readFunc: the xmlInputReadCallback
2169 * @closeFunc: the xmlInputCloseCallback
2171 * Register a new set of I/O callback for handling parser input.
2173 * Returns the registered handler number or -1 in case of error
2176 xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2177 xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2178 xmlInputCloseCallback closeFunc) {
2179 if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2182 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2183 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2184 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2185 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2186 xmlInputCallbackInitialized = 1;
2187 return(xmlInputCallbackNr++);
2190 #ifdef LIBXML_OUTPUT_ENABLED
2192 * xmlRegisterOutputCallbacks:
2193 * @matchFunc: the xmlOutputMatchCallback
2194 * @openFunc: the xmlOutputOpenCallback
2195 * @writeFunc: the xmlOutputWriteCallback
2196 * @closeFunc: the xmlOutputCloseCallback
2198 * Register a new set of I/O callback for handling output.
2200 * Returns the registered handler number or -1 in case of error
2203 xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2204 xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2205 xmlOutputCloseCallback closeFunc) {
2206 if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2209 xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2210 xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2211 xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2212 xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2213 xmlOutputCallbackInitialized = 1;
2214 return(xmlOutputCallbackNr++);
2216 #endif /* LIBXML_OUTPUT_ENABLED */
2219 * xmlRegisterDefaultInputCallbacks:
2221 * Registers the default compiled-in I/O handlers.
2224 xmlRegisterDefaultInputCallbacks(void) {
2225 if (xmlInputCallbackInitialized)
2228 xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
2229 xmlFileRead, xmlFileClose);
2231 xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2232 xmlGzfileRead, xmlGzfileClose);
2233 #endif /* HAVE_ZLIB_H */
2234 #ifdef LIBXML_LZMA_ENABLED
2235 xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen,
2236 xmlXzfileRead, xmlXzfileClose);
2237 #endif /* LIBXML_LZMA_ENABLED */
2239 #ifdef LIBXML_HTTP_ENABLED
2240 xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
2241 xmlIOHTTPRead, xmlIOHTTPClose);
2242 #endif /* LIBXML_HTTP_ENABLED */
2244 #ifdef LIBXML_FTP_ENABLED
2245 xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2246 xmlIOFTPRead, xmlIOFTPClose);
2247 #endif /* LIBXML_FTP_ENABLED */
2248 xmlInputCallbackInitialized = 1;
2251 #ifdef LIBXML_OUTPUT_ENABLED
2253 * xmlRegisterDefaultOutputCallbacks:
2255 * Registers the default compiled-in I/O handlers.
2258 xmlRegisterDefaultOutputCallbacks (void) {
2259 if (xmlOutputCallbackInitialized)
2262 xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
2263 xmlFileWrite, xmlFileClose);
2265 #ifdef LIBXML_HTTP_ENABLED
2266 xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2267 xmlIOHTTPWrite, xmlIOHTTPClosePut);
2270 /*********************************
2271 No way a-priori to distinguish between gzipped files from
2272 uncompressed ones except opening if existing then closing
2273 and saving with same compression ratio ... a pain.
2276 xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2277 xmlGzfileWrite, xmlGzfileClose);
2281 #ifdef LIBXML_FTP_ENABLED
2282 xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2283 xmlIOFTPWrite, xmlIOFTPClose);
2285 **********************************/
2286 xmlOutputCallbackInitialized = 1;
2289 #ifdef LIBXML_HTTP_ENABLED
2291 * xmlRegisterHTTPPostCallbacks:
2293 * By default, libxml submits HTTP output requests using the "PUT" method.
2294 * Calling this method changes the HTTP output method to use the "POST"
2299 xmlRegisterHTTPPostCallbacks( void ) {
2301 /* Register defaults if not done previously */
2303 if ( xmlOutputCallbackInitialized == 0 )
2304 xmlRegisterDefaultOutputCallbacks( );
2306 xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2307 xmlIOHTTPWrite, xmlIOHTTPClosePost);
2311 #endif /* LIBXML_OUTPUT_ENABLED */
2314 * xmlAllocParserInputBuffer:
2315 * @enc: the charset encoding if known
2317 * Create a buffered parser input for progressive parsing
2319 * Returns the new parser input or NULL
2321 xmlParserInputBufferPtr
2322 xmlAllocParserInputBuffer(xmlCharEncoding enc) {
2323 xmlParserInputBufferPtr ret;
2325 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2327 xmlIOErrMemory("creating input buffer");
2330 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
2331 ret->buffer = xmlBufCreateSize(2 * xmlDefaultBufferSize);
2332 if (ret->buffer == NULL) {
2336 xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
2337 ret->encoder = xmlGetCharEncodingHandler(enc);
2338 if (ret->encoder != NULL)
2339 ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
2342 ret->readcallback = NULL;
2343 ret->closecallback = NULL;
2344 ret->context = NULL;
2345 ret->compressed = -1;
2346 ret->rawconsumed = 0;
2351 #ifdef LIBXML_OUTPUT_ENABLED
2353 * xmlAllocOutputBuffer:
2354 * @encoder: the encoding converter or NULL
2356 * Create a buffered parser output
2358 * Returns the new parser output or NULL
2361 xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
2362 xmlOutputBufferPtr ret;
2364 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2366 xmlIOErrMemory("creating output buffer");
2369 memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2370 ret->buffer = xmlBufCreate();
2371 if (ret->buffer == NULL) {
2376 /* try to avoid a performance problem with Windows realloc() */
2377 if (xmlBufGetAllocationScheme(ret->buffer) == XML_BUFFER_ALLOC_EXACT)
2378 xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
2380 ret->encoder = encoder;
2381 if (encoder != NULL) {
2382 ret->conv = xmlBufCreateSize(4000);
2383 if (ret->conv == NULL) {
2389 * This call is designed to initiate the encoder state
2391 xmlCharEncOutput(ret, 1);
2394 ret->writecallback = NULL;
2395 ret->closecallback = NULL;
2396 ret->context = NULL;
2403 * xmlAllocOutputBufferInternal:
2404 * @encoder: the encoding converter or NULL
2406 * Create a buffered parser output
2408 * Returns the new parser output or NULL
2411 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
2412 xmlOutputBufferPtr ret;
2414 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2416 xmlIOErrMemory("creating output buffer");
2419 memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2420 ret->buffer = xmlBufCreate();
2421 if (ret->buffer == NULL) {
2428 * For conversion buffers we use the special IO handling
2430 xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_IO);
2432 ret->encoder = encoder;
2433 if (encoder != NULL) {
2434 ret->conv = xmlBufCreateSize(4000);
2435 if (ret->conv == NULL) {
2441 * This call is designed to initiate the encoder state
2443 xmlCharEncOutput(ret, 1);
2446 ret->writecallback = NULL;
2447 ret->closecallback = NULL;
2448 ret->context = NULL;
2454 #endif /* LIBXML_OUTPUT_ENABLED */
2457 * xmlFreeParserInputBuffer:
2458 * @in: a buffered parser input
2460 * Free up the memory used by a buffered parser input
2463 xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
2464 if (in == NULL) return;
2467 xmlBufFree(in->raw);
2470 if (in->encoder != NULL) {
2471 xmlCharEncCloseFunc(in->encoder);
2473 if (in->closecallback != NULL) {
2474 in->closecallback(in->context);
2476 if (in->buffer != NULL) {
2477 xmlBufFree(in->buffer);
2484 #ifdef LIBXML_OUTPUT_ENABLED
2486 * xmlOutputBufferClose:
2487 * @out: a buffered output
2489 * flushes and close the output I/O channel
2490 * and free up all the associated resources
2492 * Returns the number of byte written or -1 in case of error.
2495 xmlOutputBufferClose(xmlOutputBufferPtr out)
2502 if (out->writecallback != NULL)
2503 xmlOutputBufferFlush(out);
2504 if (out->closecallback != NULL) {
2505 err_rc = out->closecallback(out->context);
2507 written = out->written;
2509 xmlBufFree(out->conv);
2512 if (out->encoder != NULL) {
2513 xmlCharEncCloseFunc(out->encoder);
2515 if (out->buffer != NULL) {
2516 xmlBufFree(out->buffer);
2523 return ((err_rc == 0) ? written : err_rc);
2525 #endif /* LIBXML_OUTPUT_ENABLED */
2527 xmlParserInputBufferPtr
2528 __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2529 xmlParserInputBufferPtr ret;
2531 void *context = NULL;
2533 if (xmlInputCallbackInitialized == 0)
2534 xmlRegisterDefaultInputCallbacks();
2536 if (URI == NULL) return(NULL);
2539 * Try to find one of the input accept method accepting that scheme
2540 * Go in reverse to give precedence to user defined handlers.
2542 if (context == NULL) {
2543 for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
2544 if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
2545 (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
2546 context = xmlInputCallbackTable[i].opencallback(URI);
2547 if (context != NULL) {
2553 if (context == NULL) {
2558 * Allocate the Input buffer front-end.
2560 ret = xmlAllocParserInputBuffer(enc);
2562 ret->context = context;
2563 ret->readcallback = xmlInputCallbackTable[i].readcallback;
2564 ret->closecallback = xmlInputCallbackTable[i].closecallback;
2566 if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
2567 (strcmp(URI, "-") != 0)) {
2568 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
2569 ret->compressed = !gzdirect(context);
2571 if (((z_stream *)context)->avail_in > 4) {
2572 char *cptr, buff4[4];
2573 cptr = (char *) ((z_stream *)context)->next_in;
2574 if (gzread(context, buff4, 4) == 4) {
2575 if (strncmp(buff4, cptr, 4) == 0)
2576 ret->compressed = 0;
2578 ret->compressed = 1;
2585 #ifdef LIBXML_LZMA_ENABLED
2586 if ((xmlInputCallbackTable[i].opencallback == xmlXzfileOpen) &&
2587 (strcmp(URI, "-") != 0)) {
2588 ret->compressed = __libxml2_xzcompressed(context);
2593 xmlInputCallbackTable[i].closecallback (context);
2599 * xmlParserInputBufferCreateFilename:
2600 * @URI: a C string containing the URI or filename
2601 * @enc: the charset encoding if known
2603 * Create a buffered parser input for the progressive parsing of a file
2604 * If filename is "-' then we use stdin as the input.
2605 * Automatic support for ZLIB/Compress compressed document is provided
2606 * by default if found at compile-time.
2607 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
2609 * Returns the new parser input or NULL
2611 xmlParserInputBufferPtr
2612 xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2613 if ((xmlParserInputBufferCreateFilenameValue)) {
2614 return xmlParserInputBufferCreateFilenameValue(URI, enc);
2616 return __xmlParserInputBufferCreateFilename(URI, enc);
2619 #ifdef LIBXML_OUTPUT_ENABLED
2621 __xmlOutputBufferCreateFilename(const char *URI,
2622 xmlCharEncodingHandlerPtr encoder,
2623 int compression ATTRIBUTE_UNUSED) {
2624 xmlOutputBufferPtr ret;
2627 void *context = NULL;
2628 char *unescaped = NULL;
2630 int is_file_uri = 1;
2633 if (xmlOutputCallbackInitialized == 0)
2634 xmlRegisterDefaultOutputCallbacks();
2636 if (URI == NULL) return(NULL);
2638 puri = xmlParseURI(URI);
2641 if ((puri->scheme != NULL) &&
2642 (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
2646 * try to limit the damages of the URI unescaping code.
2648 if ((puri->scheme == NULL) ||
2649 (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
2650 unescaped = xmlURIUnescapeString(URI, 0, NULL);
2655 * Try to find one of the output accept method accepting that scheme
2656 * Go in reverse to give precedence to user defined handlers.
2657 * try with an unescaped version of the URI
2659 if (unescaped != NULL) {
2661 if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
2662 context = xmlGzfileOpenW(unescaped, compression);
2663 if (context != NULL) {
2664 ret = xmlAllocOutputBufferInternal(encoder);
2666 ret->context = context;
2667 ret->writecallback = xmlGzfileWrite;
2668 ret->closecallback = xmlGzfileClose;
2675 for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2676 if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2677 (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
2678 #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
2679 /* Need to pass compression parameter into HTTP open calls */
2680 if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2681 context = xmlIOHTTPOpenW(unescaped, compression);
2684 context = xmlOutputCallbackTable[i].opencallback(unescaped);
2685 if (context != NULL)
2693 * If this failed try with a non-escaped URI this may be a strange
2696 if (context == NULL) {
2698 if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
2699 context = xmlGzfileOpenW(URI, compression);
2700 if (context != NULL) {
2701 ret = xmlAllocOutputBufferInternal(encoder);
2703 ret->context = context;
2704 ret->writecallback = xmlGzfileWrite;
2705 ret->closecallback = xmlGzfileClose;
2711 for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2712 if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2713 (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
2714 #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
2715 /* Need to pass compression parameter into HTTP open calls */
2716 if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2717 context = xmlIOHTTPOpenW(URI, compression);
2720 context = xmlOutputCallbackTable[i].opencallback(URI);
2721 if (context != NULL)
2727 if (context == NULL) {
2732 * Allocate the Output buffer front-end.
2734 ret = xmlAllocOutputBufferInternal(encoder);
2736 ret->context = context;
2737 ret->writecallback = xmlOutputCallbackTable[i].writecallback;
2738 ret->closecallback = xmlOutputCallbackTable[i].closecallback;
2744 * xmlOutputBufferCreateFilename:
2745 * @URI: a C string containing the URI or filename
2746 * @encoder: the encoding converter or NULL
2747 * @compression: the compression ration (0 none, 9 max).
2749 * Create a buffered output for the progressive saving of a file
2750 * If filename is "-' then we use stdout as the output.
2751 * Automatic support for ZLIB/Compress compressed document is provided
2752 * by default if found at compile-time.
2753 * TODO: currently if compression is set, the library only support
2754 * writing to a local file.
2756 * Returns the new output or NULL
2759 xmlOutputBufferCreateFilename(const char *URI,
2760 xmlCharEncodingHandlerPtr encoder,
2761 int compression ATTRIBUTE_UNUSED) {
2762 if ((xmlOutputBufferCreateFilenameValue)) {
2763 return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
2765 return __xmlOutputBufferCreateFilename(URI, encoder, compression);
2767 #endif /* LIBXML_OUTPUT_ENABLED */
2770 * xmlParserInputBufferCreateFile:
2772 * @enc: the charset encoding if known
2774 * Create a buffered parser input for the progressive parsing of a FILE *
2777 * Returns the new parser input or NULL
2779 xmlParserInputBufferPtr
2780 xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
2781 xmlParserInputBufferPtr ret;
2783 if (xmlInputCallbackInitialized == 0)
2784 xmlRegisterDefaultInputCallbacks();
2786 if (file == NULL) return(NULL);
2788 ret = xmlAllocParserInputBuffer(enc);
2790 ret->context = file;
2791 ret->readcallback = xmlFileRead;
2792 ret->closecallback = xmlFileFlush;
2798 #ifdef LIBXML_OUTPUT_ENABLED
2800 * xmlOutputBufferCreateFile:
2802 * @encoder: the encoding converter or NULL
2804 * Create a buffered output for the progressive saving to a FILE *
2807 * Returns the new parser output or NULL
2810 xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
2811 xmlOutputBufferPtr ret;
2813 if (xmlOutputCallbackInitialized == 0)
2814 xmlRegisterDefaultOutputCallbacks();
2816 if (file == NULL) return(NULL);
2818 ret = xmlAllocOutputBufferInternal(encoder);
2820 ret->context = file;
2821 ret->writecallback = xmlFileWrite;
2822 ret->closecallback = xmlFileFlush;
2829 * xmlOutputBufferCreateBuffer:
2830 * @buffer: a xmlBufferPtr
2831 * @encoder: the encoding converter or NULL
2833 * Create a buffered output for the progressive saving to a xmlBuffer
2835 * Returns the new parser output or NULL
2838 xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
2839 xmlCharEncodingHandlerPtr encoder) {
2840 xmlOutputBufferPtr ret;
2842 if (buffer == NULL) return(NULL);
2844 ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
2846 (xmlOutputCloseCallback)
2847 NULL, (void *) buffer, encoder);
2853 * xmlOutputBufferGetContent:
2854 * @out: an xmlOutputBufferPtr
2856 * Gives a pointer to the data currently held in the output buffer
2858 * Returns a pointer to the data or NULL in case of error
2861 xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
2862 if ((out == NULL) || (out->buffer == NULL))
2865 return(xmlBufContent(out->buffer));
2869 * xmlOutputBufferGetSize:
2870 * @out: an xmlOutputBufferPtr
2872 * Gives the length of the data currently held in the output buffer
2874 * Returns 0 in case or error or no data is held, the size otherwise
2877 xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
2878 if ((out == NULL) || (out->buffer == NULL))
2881 return(xmlBufUse(out->buffer));
2885 #endif /* LIBXML_OUTPUT_ENABLED */
2888 * xmlParserInputBufferCreateFd:
2889 * @fd: a file descriptor number
2890 * @enc: the charset encoding if known
2892 * Create a buffered parser input for the progressive parsing for the input
2893 * from a file descriptor
2895 * Returns the new parser input or NULL
2897 xmlParserInputBufferPtr
2898 xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
2899 xmlParserInputBufferPtr ret;
2901 if (fd < 0) return(NULL);
2903 ret = xmlAllocParserInputBuffer(enc);
2905 ret->context = (void *) (ptrdiff_t) fd;
2906 ret->readcallback = xmlFdRead;
2907 ret->closecallback = xmlFdClose;
2914 * xmlParserInputBufferCreateMem:
2915 * @mem: the memory input
2916 * @size: the length of the memory block
2917 * @enc: the charset encoding if known
2919 * Create a buffered parser input for the progressive parsing for the input
2920 * from a memory area.
2922 * Returns the new parser input or NULL
2924 xmlParserInputBufferPtr
2925 xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
2926 xmlParserInputBufferPtr ret;
2929 if (size < 0) return(NULL);
2930 if (mem == NULL) return(NULL);
2932 ret = xmlAllocParserInputBuffer(enc);
2934 ret->context = (void *) mem;
2935 ret->readcallback = (xmlInputReadCallback) xmlNop;
2936 ret->closecallback = NULL;
2937 errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
2948 * xmlParserInputBufferCreateStatic:
2949 * @mem: the memory input
2950 * @size: the length of the memory block
2951 * @enc: the charset encoding if known
2953 * Create a buffered parser input for the progressive parsing for the input
2954 * from an immutable memory area. This will not copy the memory area to
2955 * the buffer, but the memory is expected to be available until the end of
2956 * the parsing, this is useful for example when using mmap'ed file.
2958 * Returns the new parser input or NULL
2960 xmlParserInputBufferPtr
2961 xmlParserInputBufferCreateStatic(const char *mem, int size,
2962 xmlCharEncoding enc) {
2963 xmlParserInputBufferPtr ret;
2965 if (size < 0) return(NULL);
2966 if (mem == NULL) return(NULL);
2968 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2970 xmlIOErrMemory("creating input buffer");
2973 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
2974 ret->buffer = xmlBufCreateStatic((void *)mem, (size_t) size);
2975 if (ret->buffer == NULL) {
2979 ret->encoder = xmlGetCharEncodingHandler(enc);
2980 if (ret->encoder != NULL)
2981 ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
2984 ret->compressed = -1;
2985 ret->context = (void *) mem;
2986 ret->readcallback = NULL;
2987 ret->closecallback = NULL;
2992 #ifdef LIBXML_OUTPUT_ENABLED
2994 * xmlOutputBufferCreateFd:
2995 * @fd: a file descriptor number
2996 * @encoder: the encoding converter or NULL
2998 * Create a buffered output for the progressive saving
2999 * to a file descriptor
3001 * Returns the new parser output or NULL
3004 xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
3005 xmlOutputBufferPtr ret;
3007 if (fd < 0) return(NULL);
3009 ret = xmlAllocOutputBufferInternal(encoder);
3011 ret->context = (void *) (ptrdiff_t) fd;
3012 ret->writecallback = xmlFdWrite;
3013 ret->closecallback = NULL;
3018 #endif /* LIBXML_OUTPUT_ENABLED */
3021 * xmlParserInputBufferCreateIO:
3022 * @ioread: an I/O read function
3023 * @ioclose: an I/O close function
3024 * @ioctx: an I/O handler
3025 * @enc: the charset encoding if known
3027 * Create a buffered parser input for the progressive parsing for the input
3028 * from an I/O handler
3030 * Returns the new parser input or NULL
3032 xmlParserInputBufferPtr
3033 xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
3034 xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
3035 xmlParserInputBufferPtr ret;
3037 if (ioread == NULL) return(NULL);
3039 ret = xmlAllocParserInputBuffer(enc);
3041 ret->context = (void *) ioctx;
3042 ret->readcallback = ioread;
3043 ret->closecallback = ioclose;
3049 #ifdef LIBXML_OUTPUT_ENABLED
3051 * xmlOutputBufferCreateIO:
3052 * @iowrite: an I/O write function
3053 * @ioclose: an I/O close function
3054 * @ioctx: an I/O handler
3055 * @encoder: the charset encoding if known
3057 * Create a buffered output for the progressive saving
3060 * Returns the new parser output or NULL
3063 xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
3064 xmlOutputCloseCallback ioclose, void *ioctx,
3065 xmlCharEncodingHandlerPtr encoder) {
3066 xmlOutputBufferPtr ret;
3068 if (iowrite == NULL) return(NULL);
3070 ret = xmlAllocOutputBufferInternal(encoder);
3072 ret->context = (void *) ioctx;
3073 ret->writecallback = iowrite;
3074 ret->closecallback = ioclose;
3079 #endif /* LIBXML_OUTPUT_ENABLED */
3082 * xmlParserInputBufferCreateFilenameDefault:
3083 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
3085 * Registers a callback for URI input file handling
3087 * Returns the old value of the registration function
3089 xmlParserInputBufferCreateFilenameFunc
3090 xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
3092 xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
3094 old = __xmlParserInputBufferCreateFilename;
3097 xmlParserInputBufferCreateFilenameValue = func;
3102 * xmlOutputBufferCreateFilenameDefault:
3103 * @func: function pointer to the new OutputBufferCreateFilenameFunc
3105 * Registers a callback for URI output file handling
3107 * Returns the old value of the registration function
3109 xmlOutputBufferCreateFilenameFunc
3110 xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
3112 xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
3113 #ifdef LIBXML_OUTPUT_ENABLED
3115 old = __xmlOutputBufferCreateFilename;
3118 xmlOutputBufferCreateFilenameValue = func;
3123 * xmlParserInputBufferPush:
3124 * @in: a buffered parser input
3125 * @len: the size in bytes of the array.
3126 * @buf: an char array
3128 * Push the content of the arry in the input buffer
3129 * This routine handle the I18N transcoding to internal UTF-8
3130 * This is used when operating the parser in progressive (push) mode.
3132 * Returns the number of chars read and stored in the buffer, or -1
3136 xmlParserInputBufferPush(xmlParserInputBufferPtr in,
3137 int len, const char *buf) {
3141 if (len < 0) return(0);
3142 if ((in == NULL) || (in->error)) return(-1);
3143 if (in->encoder != NULL) {
3147 * Store the data in the incoming raw buffer
3149 if (in->raw == NULL) {
3150 in->raw = xmlBufCreate();
3152 ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
3157 * convert as much as possible to the parser reading buffer.
3159 use = xmlBufUse(in->raw);
3160 nbchars = xmlCharEncInput(in, 1);
3162 xmlIOErr(XML_IO_ENCODER, NULL);
3163 in->error = XML_IO_ENCODER;
3166 in->rawconsumed += (use - xmlBufUse(in->raw));
3169 ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
3174 xmlGenericError(xmlGenericErrorContext,
3175 "I/O: pushed %d chars, buffer %d/%d\n",
3176 nbchars, xmlBufUse(in->buffer), xmlBufLength(in->buffer));
3184 * When reading from an Input channel indicated end of file or error
3185 * don't reread from it again.
3188 endOfInput (void * context ATTRIBUTE_UNUSED,
3189 char * buffer ATTRIBUTE_UNUSED,
3190 int len ATTRIBUTE_UNUSED) {
3195 * xmlParserInputBufferGrow:
3196 * @in: a buffered parser input
3197 * @len: indicative value of the amount of chars to read
3199 * Grow up the content of the input buffer, the old data are preserved
3200 * This routine handle the I18N transcoding to internal UTF-8
3201 * This routine is used when operating the parser in normal (pull) mode
3203 * TODO: one should be able to remove one extra copy by copying directly
3204 * onto in->buffer or in->raw
3206 * Returns the number of chars read and stored in the buffer, or -1
3210 xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
3211 char *buffer = NULL;
3215 if ((in == NULL) || (in->error)) return(-1);
3216 if ((len <= MINLEN) && (len != 4))
3219 if (xmlBufAvail(in->buffer) <= 0) {
3220 xmlIOErr(XML_IO_BUFFER_FULL, NULL);
3221 in->error = XML_IO_BUFFER_FULL;
3225 if (xmlBufGrow(in->buffer, len + 1) < 0) {
3226 xmlIOErrMemory("growing input buffer");
3227 in->error = XML_ERR_NO_MEMORY;
3230 buffer = (char *)xmlBufEnd(in->buffer);
3233 * Call the read method for this I/O type.
3235 if (in->readcallback != NULL) {
3236 res = in->readcallback(in->context, &buffer[0], len);
3238 in->readcallback = endOfInput;
3240 xmlIOErr(XML_IO_NO_INPUT, NULL);
3241 in->error = XML_IO_NO_INPUT;
3249 * try to establish compressed status of input if not done already
3251 if (in->compressed == -1) {
3252 #ifdef LIBXML_LZMA_ENABLED
3253 if (in->readcallback == xmlXzfileRead)
3254 in->compressed = __libxml2_xzcompressed(in->context);
3259 if (in->encoder != NULL) {
3263 * Store the data in the incoming raw buffer
3265 if (in->raw == NULL) {
3266 in->raw = xmlBufCreate();
3268 res = xmlBufAdd(in->raw, (const xmlChar *) buffer, len);
3273 * convert as much as possible to the parser reading buffer.
3275 use = xmlBufUse(in->raw);
3276 nbchars = xmlCharEncInput(in, 1);
3278 xmlIOErr(XML_IO_ENCODER, NULL);
3279 in->error = XML_IO_ENCODER;
3282 in->rawconsumed += (use - xmlBufUse(in->raw));
3285 xmlBufAddLen(in->buffer, nbchars);
3288 xmlGenericError(xmlGenericErrorContext,
3289 "I/O: read %d chars, buffer %d\n",
3290 nbchars, xmlBufUse(in->buffer));
3296 * xmlParserInputBufferRead:
3297 * @in: a buffered parser input
3298 * @len: indicative value of the amount of chars to read
3300 * Refresh the content of the input buffer, the old data are considered
3302 * This routine handle the I18N transcoding to internal UTF-8
3304 * Returns the number of chars read and stored in the buffer, or -1
3308 xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
3309 if ((in == NULL) || (in->error)) return(-1);
3310 if (in->readcallback != NULL)
3311 return(xmlParserInputBufferGrow(in, len));
3312 else if (xmlBufGetAllocationScheme(in->buffer) == XML_BUFFER_ALLOC_IMMUTABLE)
3318 #ifdef LIBXML_OUTPUT_ENABLED
3320 * xmlOutputBufferWrite:
3321 * @out: a buffered parser output
3322 * @len: the size in bytes of the array.
3323 * @buf: an char array
3325 * Write the content of the array in the output I/O buffer
3326 * This routine handle the I18N transcoding from internal UTF-8
3327 * The buffer is lossless, i.e. will store in case of partial
3328 * or delayed writes.
3330 * Returns the number of chars immediately written, or -1
3334 xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
3335 int nbchars = 0; /* number of chars to output to I/O */
3336 int ret; /* return from function call */
3337 int written = 0; /* number of char written to I/O so far */
3338 int chunk; /* number of byte curreent processed from buf */
3340 if ((out == NULL) || (out->error)) return(-1);
3341 if (len < 0) return(0);
3342 if (out->error) return(-1);
3346 if (chunk > 4 * MINLEN)
3350 * first handle encoding stuff.
3352 if (out->encoder != NULL) {
3354 * Store the data in the incoming raw buffer
3356 if (out->conv == NULL) {
3357 out->conv = xmlBufCreate();
3359 ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
3363 if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len))
3367 * convert as much as possible to the parser reading buffer.
3369 ret = xmlCharEncOutput(out, 0);
3370 if ((ret < 0) && (ret != -3)) {
3371 xmlIOErr(XML_IO_ENCODER, NULL);
3372 out->error = XML_IO_ENCODER;
3375 nbchars = xmlBufUse(out->conv);
3377 ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
3380 nbchars = xmlBufUse(out->buffer);
3385 if ((nbchars < MINLEN) && (len <= 0))
3388 if (out->writecallback) {
3390 * second write the stuff to the I/O channel
3392 if (out->encoder != NULL) {
3393 ret = out->writecallback(out->context,
3394 (const char *)xmlBufContent(out->conv), nbchars);
3396 xmlBufShrink(out->conv, ret);
3398 ret = out->writecallback(out->context,
3399 (const char *)xmlBufContent(out->buffer), nbchars);
3401 xmlBufShrink(out->buffer, ret);
3404 xmlIOErr(XML_IO_WRITE, NULL);
3405 out->error = XML_IO_WRITE;
3408 out->written += ret;
3415 xmlGenericError(xmlGenericErrorContext,
3416 "I/O: wrote %d chars\n", written);
3423 * @out: a pointer to an array of bytes to store the result
3424 * @outlen: the length of @out
3425 * @in: a pointer to an array of unescaped UTF-8 bytes
3426 * @inlen: the length of @in
3428 * Take a block of UTF-8 chars in and escape them.
3429 * Returns 0 if success, or -1 otherwise
3430 * The value of @inlen after return is the number of octets consumed
3431 * if the return value is positive, else unpredictable.
3432 * The value of @outlen after return is the number of octets consumed.
3435 xmlEscapeContent(unsigned char* out, int *outlen,
3436 const xmlChar* in, int *inlen) {
3437 unsigned char* outstart = out;
3438 const unsigned char* base = in;
3439 unsigned char* outend = out + *outlen;
3440 const unsigned char* inend;
3442 inend = in + (*inlen);
3444 while ((in < inend) && (out < outend)) {
3446 if (outend - out < 4) break;
3451 } else if (*in == '>') {
3452 if (outend - out < 4) break;
3457 } else if (*in == '&') {
3458 if (outend - out < 5) break;
3464 } else if (*in == '\r') {
3465 if (outend - out < 5) break;
3472 *out++ = (unsigned char) *in;
3476 *outlen = out - outstart;
3482 * xmlOutputBufferWriteEscape:
3483 * @out: a buffered parser output
3484 * @str: a zero terminated UTF-8 string
3485 * @escaping: an optional escaping function (or NULL)
3487 * Write the content of the string in the output I/O buffer
3488 * This routine escapes the caracters and then handle the I18N
3489 * transcoding from internal UTF-8
3490 * The buffer is lossless, i.e. will store in case of partial
3491 * or delayed writes.
3493 * Returns the number of chars immediately written, or -1
3497 xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
3498 xmlCharEncodingOutputFunc escaping) {
3499 int nbchars = 0; /* number of chars to output to I/O */
3500 int ret; /* return from function call */
3501 int written = 0; /* number of char written to I/O so far */
3502 int oldwritten=0;/* loop guard */
3503 int chunk; /* number of byte currently processed from str */
3504 int len; /* number of bytes in str */
3505 int cons; /* byte from str consumed */
3507 if ((out == NULL) || (out->error) || (str == NULL) ||
3508 (out->buffer == NULL) ||
3509 (xmlBufGetAllocationScheme(out->buffer) == XML_BUFFER_ALLOC_IMMUTABLE))
3511 len = strlen((const char *)str);
3512 if (len < 0) return(0);
3513 if (out->error) return(-1);
3514 if (escaping == NULL) escaping = xmlEscapeContent;
3517 oldwritten = written;
3520 * how many bytes to consume and how many bytes to store.
3523 chunk = xmlBufAvail(out->buffer) - 1;
3526 * make sure we have enough room to save first, if this is
3527 * not the case force a flush, but make sure we stay in the loop
3530 if (xmlBufGrow(out->buffer, 100) < 0)
3537 * first handle encoding stuff.
3539 if (out->encoder != NULL) {
3541 * Store the data in the incoming raw buffer
3543 if (out->conv == NULL) {
3544 out->conv = xmlBufCreate();
3546 ret = escaping(xmlBufEnd(out->buffer) ,
3547 &chunk, str, &cons);
3548 if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
3550 xmlBufAddLen(out->buffer, chunk);
3552 if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
3556 * convert as much as possible to the output buffer.
3558 ret = xmlCharEncOutput(out, 0);
3559 if ((ret < 0) && (ret != -3)) {
3560 xmlIOErr(XML_IO_ENCODER, NULL);
3561 out->error = XML_IO_ENCODER;
3564 nbchars = xmlBufUse(out->conv);
3566 ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
3567 if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
3569 xmlBufAddLen(out->buffer, chunk);
3570 nbchars = xmlBufUse(out->buffer);
3575 if ((nbchars < MINLEN) && (len <= 0))
3578 if (out->writecallback) {
3580 * second write the stuff to the I/O channel
3582 if (out->encoder != NULL) {
3583 ret = out->writecallback(out->context,
3584 (const char *)xmlBufContent(out->conv), nbchars);
3586 xmlBufShrink(out->conv, ret);
3588 ret = out->writecallback(out->context,
3589 (const char *)xmlBufContent(out->buffer), nbchars);
3591 xmlBufShrink(out->buffer, ret);
3594 xmlIOErr(XML_IO_WRITE, NULL);
3595 out->error = XML_IO_WRITE;
3598 out->written += ret;
3599 } else if (xmlBufAvail(out->buffer) < MINLEN) {
3600 xmlBufGrow(out->buffer, MINLEN);
3603 } while ((len > 0) && (oldwritten != written));
3607 xmlGenericError(xmlGenericErrorContext,
3608 "I/O: wrote %d chars\n", written);
3614 * xmlOutputBufferWriteString:
3615 * @out: a buffered parser output
3616 * @str: a zero terminated C string
3618 * Write the content of the string in the output I/O buffer
3619 * This routine handle the I18N transcoding from internal UTF-8
3620 * The buffer is lossless, i.e. will store in case of partial
3621 * or delayed writes.
3623 * Returns the number of chars immediately written, or -1
3627 xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
3630 if ((out == NULL) || (out->error)) return(-1);
3636 return(xmlOutputBufferWrite(out, len, str));
3641 * xmlOutputBufferFlush:
3642 * @out: a buffered output
3644 * flushes the output I/O channel
3646 * Returns the number of byte written or -1 in case of error.
3649 xmlOutputBufferFlush(xmlOutputBufferPtr out) {
3650 int nbchars = 0, ret = 0;
3652 if ((out == NULL) || (out->error)) return(-1);
3654 * first handle encoding stuff.
3656 if ((out->conv != NULL) && (out->encoder != NULL)) {
3658 * convert as much as possible to the parser output buffer.
3661 nbchars = xmlCharEncOutput(out, 0);
3663 xmlIOErr(XML_IO_ENCODER, NULL);
3664 out->error = XML_IO_ENCODER;
3671 * second flush the stuff to the I/O channel
3673 if ((out->conv != NULL) && (out->encoder != NULL) &&
3674 (out->writecallback != NULL)) {
3675 ret = out->writecallback(out->context,
3676 (const char *)xmlBufContent(out->conv),
3677 xmlBufUse(out->conv));
3679 xmlBufShrink(out->conv, ret);
3680 } else if (out->writecallback != NULL) {
3681 ret = out->writecallback(out->context,
3682 (const char *)xmlBufContent(out->buffer),
3683 xmlBufUse(out->buffer));
3685 xmlBufShrink(out->buffer, ret);
3688 xmlIOErr(XML_IO_FLUSH, NULL);
3689 out->error = XML_IO_FLUSH;
3692 out->written += ret;
3695 xmlGenericError(xmlGenericErrorContext,
3696 "I/O: flushed %d chars\n", ret);
3700 #endif /* LIBXML_OUTPUT_ENABLED */
3703 * xmlParserGetDirectory:
3704 * @filename: the path to a file
3706 * lookup the directory for that file
3708 * Returns a new allocated string containing the directory, or NULL.
3711 xmlParserGetDirectory(const char *filename) {
3716 #ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */
3720 if (xmlInputCallbackInitialized == 0)
3721 xmlRegisterDefaultInputCallbacks();
3723 if (filename == NULL) return(NULL);
3725 #if defined(_WIN32) && !defined(__CYGWIN__)
3726 # define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
3728 # define IS_XMLPGD_SEP(ch) (ch=='/')
3731 strncpy(dir, filename, 1023);
3733 cur = &dir[strlen(dir)];
3735 if (IS_XMLPGD_SEP(*cur)) break;
3738 if (IS_XMLPGD_SEP(*cur)) {
3739 if (cur == dir) dir[1] = 0;
3741 ret = xmlMemStrdup(dir);
3743 if (getcwd(dir, 1024) != NULL) {
3745 ret = xmlMemStrdup(dir);
3749 #undef IS_XMLPGD_SEP
3752 /****************************************************************
3754 * External entities loading *
3756 ****************************************************************/
3759 * xmlCheckHTTPInput:
3760 * @ctxt: an XML parser context
3761 * @ret: an XML parser input
3763 * Check an input in case it was created from an HTTP stream, in that
3764 * case it will handle encoding and update of the base URL in case of
3765 * redirection. It also checks for HTTP errors in which case the input
3766 * is cleanly freed up and an appropriate error is raised in context
3768 * Returns the input or NULL in case of HTTP error.
3771 xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
3772 #ifdef LIBXML_HTTP_ENABLED
3773 if ((ret != NULL) && (ret->buf != NULL) &&
3774 (ret->buf->readcallback == xmlIOHTTPRead) &&
3775 (ret->buf->context != NULL)) {
3776 const char *encoding;
3781 code = xmlNanoHTTPReturnCode(ret->buf->context);
3784 if (ret->filename != NULL)
3785 __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
3786 (const char *) ret->filename);
3788 __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
3789 xmlFreeInputStream(ret);
3793 mime = xmlNanoHTTPMimeType(ret->buf->context);
3794 if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
3795 (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
3796 encoding = xmlNanoHTTPEncoding(ret->buf->context);
3797 if (encoding != NULL) {
3798 xmlCharEncodingHandlerPtr handler;
3800 handler = xmlFindCharEncodingHandler(encoding);
3801 if (handler != NULL) {
3802 xmlSwitchInputEncoding(ctxt, ret, handler);
3804 __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
3805 "Unknown encoding %s",
3806 BAD_CAST encoding, NULL);
3808 if (ret->encoding == NULL)
3809 ret->encoding = xmlStrdup(BAD_CAST encoding);
3812 } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
3815 redir = xmlNanoHTTPRedir(ret->buf->context);
3816 if (redir != NULL) {
3817 if (ret->filename != NULL)
3818 xmlFree((xmlChar *) ret->filename);
3819 if (ret->directory != NULL) {
3820 xmlFree((xmlChar *) ret->directory);
3821 ret->directory = NULL;
3824 (char *) xmlStrdup((const xmlChar *) redir);
3832 static int xmlNoNetExists(const char *URL) {
3838 if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
3839 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3844 else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
3845 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3853 return xmlCheckFilename(path);
3856 #ifdef LIBXML_CATALOG_ENABLED
3859 * xmlResolveResourceFromCatalog:
3860 * @URL: the URL for the entity to load
3861 * @ID: the System ID for the entity to load
3862 * @ctxt: the context in which the entity is called or NULL
3864 * Resolves the URL and ID against the appropriate catalog.
3865 * This function is used by xmlDefaultExternalEntityLoader and
3866 * xmlNoNetExternalEntityLoader.
3868 * Returns a new allocated URL, or NULL.
3871 xmlResolveResourceFromCatalog(const char *URL, const char *ID,
3872 xmlParserCtxtPtr ctxt) {
3873 xmlChar *resource = NULL;
3874 xmlCatalogAllow pref;
3877 * If the resource doesn't exists as a file,
3878 * try to load it from the resource pointed in the catalogs
3880 pref = xmlCatalogGetDefaults();
3882 if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
3886 if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3887 ((pref == XML_CATA_ALLOW_ALL) ||
3888 (pref == XML_CATA_ALLOW_DOCUMENT))) {
3889 resource = xmlCatalogLocalResolve(ctxt->catalogs,
3890 (const xmlChar *)ID,
3891 (const xmlChar *)URL);
3894 * Try a global lookup
3896 if ((resource == NULL) &&
3897 ((pref == XML_CATA_ALLOW_ALL) ||
3898 (pref == XML_CATA_ALLOW_GLOBAL))) {
3899 resource = xmlCatalogResolve((const xmlChar *)ID,
3900 (const xmlChar *)URL);
3902 if ((resource == NULL) && (URL != NULL))
3903 resource = xmlStrdup((const xmlChar *) URL);
3906 * TODO: do an URI lookup on the reference
3908 if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
3909 xmlChar *tmp = NULL;
3911 if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3912 ((pref == XML_CATA_ALLOW_ALL) ||
3913 (pref == XML_CATA_ALLOW_DOCUMENT))) {
3914 tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
3916 if ((tmp == NULL) &&
3917 ((pref == XML_CATA_ALLOW_ALL) ||
3918 (pref == XML_CATA_ALLOW_GLOBAL))) {
3919 tmp = xmlCatalogResolveURI(resource);
3935 * xmlDefaultExternalEntityLoader:
3936 * @URL: the URL for the entity to load
3937 * @ID: the System ID for the entity to load
3938 * @ctxt: the context in which the entity is called or NULL
3940 * By default we don't load external entitites, yet.
3942 * Returns a new allocated xmlParserInputPtr, or NULL.
3944 static xmlParserInputPtr
3945 xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
3946 xmlParserCtxtPtr ctxt)
3948 xmlParserInputPtr ret = NULL;
3949 xmlChar *resource = NULL;
3951 #ifdef DEBUG_EXTERNAL_ENTITIES
3952 xmlGenericError(xmlGenericErrorContext,
3953 "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
3955 if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
3956 int options = ctxt->options;
3958 ctxt->options -= XML_PARSE_NONET;
3959 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
3960 ctxt->options = options;
3963 #ifdef LIBXML_CATALOG_ENABLED
3964 resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
3967 if (resource == NULL)
3968 resource = (xmlChar *) URL;
3970 if (resource == NULL) {
3973 __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
3976 ret = xmlNewInputFromFile(ctxt, (const char *) resource);
3977 if ((resource != NULL) && (resource != (xmlChar *) URL))
3982 static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
3983 xmlDefaultExternalEntityLoader;
3986 * xmlSetExternalEntityLoader:
3987 * @f: the new entity resolver function
3989 * Changes the defaultexternal entity resolver function for the application
3992 xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
3993 xmlCurrentExternalEntityLoader = f;
3997 * xmlGetExternalEntityLoader:
3999 * Get the default external entity resolver function for the application
4001 * Returns the xmlExternalEntityLoader function pointer
4003 xmlExternalEntityLoader
4004 xmlGetExternalEntityLoader(void) {
4005 return(xmlCurrentExternalEntityLoader);
4009 * xmlLoadExternalEntity:
4010 * @URL: the URL for the entity to load
4011 * @ID: the Public ID for the entity to load
4012 * @ctxt: the context in which the entity is called or NULL
4014 * Load an external entity, note that the use of this function for
4015 * unparsed entities may generate problems
4017 * Returns the xmlParserInputPtr or NULL
4020 xmlLoadExternalEntity(const char *URL, const char *ID,
4021 xmlParserCtxtPtr ctxt) {
4022 if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
4023 char *canonicFilename;
4024 xmlParserInputPtr ret;
4026 canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
4027 if (canonicFilename == NULL) {
4028 xmlIOErrMemory("building canonical path\n");
4032 ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
4033 xmlFree(canonicFilename);
4036 return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
4039 /************************************************************************
4041 * Disabling Network access *
4043 ************************************************************************/
4046 * xmlNoNetExternalEntityLoader:
4047 * @URL: the URL for the entity to load
4048 * @ID: the System ID for the entity to load
4049 * @ctxt: the context in which the entity is called or NULL
4051 * A specific entity loader disabling network accesses, though still
4052 * allowing local catalog accesses for resolution.
4054 * Returns a new allocated xmlParserInputPtr, or NULL.
4057 xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
4058 xmlParserCtxtPtr ctxt) {
4059 xmlParserInputPtr input = NULL;
4060 xmlChar *resource = NULL;
4062 #ifdef LIBXML_CATALOG_ENABLED
4063 resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
4066 if (resource == NULL)
4067 resource = (xmlChar *) URL;
4069 if (resource != NULL) {
4070 if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
4071 (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
4072 xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
4073 if (resource != (xmlChar *) URL)
4078 input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
4079 if (resource != (xmlChar *) URL)
4084 #define bottom_xmlIO
4085 #include "elfgcchack.h"