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
20 #ifdef HAVE_SYS_TYPES_H
21 #include <sys/types.h>
23 #ifdef HAVE_SYS_STAT_H
42 #if defined(WIN32) || defined(_WIN32)
46 #if defined(_WIN32_WCE)
47 #include <winnls.h> /* for CP_UTF8 */
50 /* Figure a portable way to know if a file is a directory. */
53 /* MS C library seems to define stat and _stat. The definition
54 is identical. Still, mapping them to each other causes a warning. */
56 # define stat(x,y) _stat(x,y)
62 # if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
70 # define S_ISDIR(x) _S_ISDIR(x)
75 # define S_IFMT _S_IFMT
79 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
86 #include <libxml/xmlmemory.h>
87 #include <libxml/parser.h>
88 #include <libxml/parserInternals.h>
89 #include <libxml/xmlIO.h>
90 #include <libxml/uri.h>
91 #include <libxml/nanohttp.h>
92 #include <libxml/nanoftp.h>
93 #include <libxml/xmlerror.h>
94 #ifdef LIBXML_CATALOG_ENABLED
95 #include <libxml/catalog.h>
97 #include <libxml/globals.h>
99 /* #define VERBOSE_FAILURE */
100 /* #define DEBUG_EXTERNAL_ENTITIES */
101 /* #define DEBUG_INPUT */
110 * Input I/O callback sets
112 typedef struct _xmlInputCallback {
113 xmlInputMatchCallback matchcallback;
114 xmlInputOpenCallback opencallback;
115 xmlInputReadCallback readcallback;
116 xmlInputCloseCallback closecallback;
119 #define MAX_INPUT_CALLBACK 15
121 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
122 static int xmlInputCallbackNr = 0;
123 static int xmlInputCallbackInitialized = 0;
125 #ifdef LIBXML_OUTPUT_ENABLED
127 * Output I/O callback sets
129 typedef struct _xmlOutputCallback {
130 xmlOutputMatchCallback matchcallback;
131 xmlOutputOpenCallback opencallback;
132 xmlOutputWriteCallback writecallback;
133 xmlOutputCloseCallback closecallback;
136 #define MAX_OUTPUT_CALLBACK 15
138 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
139 static int xmlOutputCallbackNr = 0;
140 static int xmlOutputCallbackInitialized = 0;
143 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
144 #endif /* LIBXML_OUTPUT_ENABLED */
146 /************************************************************************
148 * Tree memory error handler *
150 ************************************************************************/
152 static const char *IOerr[] = {
153 "Unknown IO error", /* UNKNOWN */
154 "Permission denied", /* EACCES */
155 "Resource temporarily unavailable",/* EAGAIN */
156 "Bad file descriptor", /* EBADF */
157 "Bad message", /* EBADMSG */
158 "Resource busy", /* EBUSY */
159 "Operation canceled", /* ECANCELED */
160 "No child processes", /* ECHILD */
161 "Resource deadlock avoided",/* EDEADLK */
162 "Domain error", /* EDOM */
163 "File exists", /* EEXIST */
164 "Bad address", /* EFAULT */
165 "File too large", /* EFBIG */
166 "Operation in progress", /* EINPROGRESS */
167 "Interrupted function call",/* EINTR */
168 "Invalid argument", /* EINVAL */
169 "Input/output error", /* EIO */
170 "Is a directory", /* EISDIR */
171 "Too many open files", /* EMFILE */
172 "Too many links", /* EMLINK */
173 "Inappropriate message buffer length",/* EMSGSIZE */
174 "Filename too long", /* ENAMETOOLONG */
175 "Too many open files in system",/* ENFILE */
176 "No such device", /* ENODEV */
177 "No such file or directory",/* ENOENT */
178 "Exec format error", /* ENOEXEC */
179 "No locks available", /* ENOLCK */
180 "Not enough space", /* ENOMEM */
181 "No space left on device", /* ENOSPC */
182 "Function not implemented", /* ENOSYS */
183 "Not a directory", /* ENOTDIR */
184 "Directory not empty", /* ENOTEMPTY */
185 "Not supported", /* ENOTSUP */
186 "Inappropriate I/O control operation",/* ENOTTY */
187 "No such device or address",/* ENXIO */
188 "Operation not permitted", /* EPERM */
189 "Broken pipe", /* EPIPE */
190 "Result too large", /* ERANGE */
191 "Read-only file system", /* EROFS */
192 "Invalid seek", /* ESPIPE */
193 "No such process", /* ESRCH */
194 "Operation timed out", /* ETIMEDOUT */
195 "Improper link", /* EXDEV */
196 "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
197 "encoder error", /* XML_IO_ENCODER */
203 "not a socket", /* ENOTSOCK */
204 "already connected", /* EISCONN */
205 "connection refused", /* ECONNREFUSED */
206 "unreachable network", /* ENETUNREACH */
207 "adddress in use", /* EADDRINUSE */
208 "already in use", /* EALREADY */
209 "unknown address familly", /* EAFNOSUPPORT */
212 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
214 * __xmlIOWin32UTF8ToWChar:
215 * @u8String: uft-8 string
217 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
220 __xmlIOWin32UTF8ToWChar(const char *u8String)
222 wchar_t *wString = NULL;
226 MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
229 wString = xmlMalloc(wLen * sizeof(wchar_t));
231 if (MultiByteToWideChar
232 (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
246 * @extra: extra informations
248 * Handle an out of memory condition
251 xmlIOErrMemory(const char *extra)
253 __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
258 * @code: the error number
260 * @extra: extra informations
262 * Handle an I/O error
265 __xmlIOErr(int domain, int code, const char *extra)
271 if (errno == 0) code = 0;
273 else if (errno == EACCES) code = XML_IO_EACCES;
276 else if (errno == EAGAIN) code = XML_IO_EAGAIN;
279 else if (errno == EBADF) code = XML_IO_EBADF;
282 else if (errno == EBADMSG) code = XML_IO_EBADMSG;
285 else if (errno == EBUSY) code = XML_IO_EBUSY;
288 else if (errno == ECANCELED) code = XML_IO_ECANCELED;
291 else if (errno == ECHILD) code = XML_IO_ECHILD;
294 else if (errno == EDEADLK) code = XML_IO_EDEADLK;
297 else if (errno == EDOM) code = XML_IO_EDOM;
300 else if (errno == EEXIST) code = XML_IO_EEXIST;
303 else if (errno == EFAULT) code = XML_IO_EFAULT;
306 else if (errno == EFBIG) code = XML_IO_EFBIG;
309 else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
312 else if (errno == EINTR) code = XML_IO_EINTR;
315 else if (errno == EINVAL) code = XML_IO_EINVAL;
318 else if (errno == EIO) code = XML_IO_EIO;
321 else if (errno == EISDIR) code = XML_IO_EISDIR;
324 else if (errno == EMFILE) code = XML_IO_EMFILE;
327 else if (errno == EMLINK) code = XML_IO_EMLINK;
330 else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
333 else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
336 else if (errno == ENFILE) code = XML_IO_ENFILE;
339 else if (errno == ENODEV) code = XML_IO_ENODEV;
342 else if (errno == ENOENT) code = XML_IO_ENOENT;
345 else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
348 else if (errno == ENOLCK) code = XML_IO_ENOLCK;
351 else if (errno == ENOMEM) code = XML_IO_ENOMEM;
354 else if (errno == ENOSPC) code = XML_IO_ENOSPC;
357 else if (errno == ENOSYS) code = XML_IO_ENOSYS;
360 else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
363 else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
366 else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
369 else if (errno == ENOTTY) code = XML_IO_ENOTTY;
372 else if (errno == ENXIO) code = XML_IO_ENXIO;
375 else if (errno == EPERM) code = XML_IO_EPERM;
378 else if (errno == EPIPE) code = XML_IO_EPIPE;
381 else if (errno == ERANGE) code = XML_IO_ERANGE;
384 else if (errno == EROFS) code = XML_IO_EROFS;
387 else if (errno == ESPIPE) code = XML_IO_ESPIPE;
390 else if (errno == ESRCH) code = XML_IO_ESRCH;
393 else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
396 else if (errno == EXDEV) code = XML_IO_EXDEV;
399 else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
402 else if (errno == EISCONN) code = XML_IO_EISCONN;
405 else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
408 else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
411 else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
414 else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
417 else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
420 else if (errno == EALREADY) code = XML_IO_EALREADY;
423 else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
425 else code = XML_IO_UNKNOWN;
426 #endif /* HAVE_ERRNO_H */
429 if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
430 if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
432 __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
437 * @code: the error number
438 * @extra: extra informations
440 * Handle an I/O error
443 xmlIOErr(int code, const char *extra)
445 __xmlIOErr(XML_FROM_IO, code, extra);
450 * @ctx: the parser context
451 * @extra: extra informations
453 * Handle a resource access error
456 __xmlLoaderErr(void *ctx, const char *msg, const char *filename)
458 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
459 xmlStructuredErrorFunc schannel = NULL;
460 xmlGenericErrorFunc channel = NULL;
462 xmlErrorLevel level = XML_ERR_ERROR;
464 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
465 (ctxt->instate == XML_PARSER_EOF))
467 if ((ctxt != NULL) && (ctxt->sax != NULL)) {
468 if (ctxt->validate) {
469 channel = ctxt->sax->error;
470 level = XML_ERR_ERROR;
472 channel = ctxt->sax->warning;
473 level = XML_ERR_WARNING;
475 if (ctxt->sax->initialized == XML_SAX2_MAGIC)
476 schannel = ctxt->sax->serror;
477 data = ctxt->userData;
479 __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
480 XML_IO_LOAD_ERROR, level, NULL, 0,
481 filename, NULL, NULL, 0, 0,
486 /************************************************************************
488 * Tree memory error handler *
490 ************************************************************************/
492 * xmlNormalizeWindowsPath:
493 * @path: the input file path
495 * This function is obsolete. Please see xmlURIFromPath in uri.c for
498 * Returns a canonicalized version of the path
501 xmlNormalizeWindowsPath(const xmlChar *path)
503 return xmlCanonicPath(path);
507 * xmlCleanupInputCallbacks:
509 * clears the entire input callback table. this includes the
513 xmlCleanupInputCallbacks(void)
517 if (!xmlInputCallbackInitialized)
520 for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
521 xmlInputCallbackTable[i].matchcallback = NULL;
522 xmlInputCallbackTable[i].opencallback = NULL;
523 xmlInputCallbackTable[i].readcallback = NULL;
524 xmlInputCallbackTable[i].closecallback = NULL;
527 xmlInputCallbackNr = 0;
528 xmlInputCallbackInitialized = 0;
532 * xmlPopInputCallbacks:
534 * Clear the top input callback from the input stack. this includes the
537 * Returns the number of input callback registered or -1 in case of error.
540 xmlPopInputCallbacks(void)
542 if (!xmlInputCallbackInitialized)
545 if (xmlInputCallbackNr <= 0)
548 xmlInputCallbackNr--;
549 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
550 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
551 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
552 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
554 return(xmlInputCallbackNr);
557 #ifdef LIBXML_OUTPUT_ENABLED
559 * xmlCleanupOutputCallbacks:
561 * clears the entire output callback table. this includes the
562 * compiled-in I/O callbacks.
565 xmlCleanupOutputCallbacks(void)
569 if (!xmlOutputCallbackInitialized)
572 for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
573 xmlOutputCallbackTable[i].matchcallback = NULL;
574 xmlOutputCallbackTable[i].opencallback = NULL;
575 xmlOutputCallbackTable[i].writecallback = NULL;
576 xmlOutputCallbackTable[i].closecallback = NULL;
579 xmlOutputCallbackNr = 0;
580 xmlOutputCallbackInitialized = 0;
582 #endif /* LIBXML_OUTPUT_ENABLED */
584 /************************************************************************
586 * Standard I/O for file accesses *
588 ************************************************************************/
590 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
594 * @path: the path in utf-8 encoding
595 * @mode: type of access (0 - read, 1 - write)
597 * function opens the file specified by @path
601 xmlWrapOpenUtf8(const char *path,int mode)
606 wPath = __xmlIOWin32UTF8ToWChar(path);
609 fd = _wfopen(wPath, mode ? L"wb" : L"rb");
612 /* maybe path in native encoding */
614 fd = fopen(path, mode ? "wb" : "rb");
621 xmlWrapGzOpenUtf8(const char *path, const char *mode)
626 fd = gzopen (path, mode);
630 wPath = __xmlIOWin32UTF8ToWChar(path);
633 int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
635 m |= (strstr(mode, "b") ? _O_BINARY : 0);
637 d = _wopen(wPath, m);
639 fd = gzdopen(d, mode);
649 * @path: the path in utf-8 encoding
650 * @info: structure that stores results
652 * function obtains information about the file or directory
656 xmlWrapStatUtf8(const char *path,struct stat *info)
662 wPath = __xmlIOWin32UTF8ToWChar(path);
665 retval = _wstat(wPath,info);
668 /* maybe path in native encoding */
670 retval = stat(path,info);
680 * @mode: type of access (0 - read, 1 - write)
682 * function opens the file specified by @path
686 xmlWrapOpenNative(const char *path,int mode)
688 return fopen(path,mode ? "wb" : "rb");
694 * @info: structure that stores results
696 * function obtains information about the file or directory
700 xmlWrapStatNative(const char *path,struct stat *info)
703 return stat(path,info);
709 typedef int (* xmlWrapStatFunc) (const char *f, struct stat *s);
710 static xmlWrapStatFunc xmlWrapStat = xmlWrapStatNative;
711 typedef FILE* (* xmlWrapOpenFunc)(const char *f,int mode);
712 static xmlWrapOpenFunc xmlWrapOpen = xmlWrapOpenNative;
714 typedef gzFile (* xmlWrapGzOpenFunc) (const char *f, const char *mode);
715 static xmlWrapGzOpenFunc xmlWrapGzOpen = gzopen;
718 * xmlInitPlatformSpecificIo:
720 * Initialize platform specific features.
723 xmlInitPlatformSpecificIo(void)
725 static int xmlPlatformIoInitialized = 0;
728 if(xmlPlatformIoInitialized)
731 osvi.dwOSVersionInfoSize = sizeof(osvi);
733 if(GetVersionEx(&osvi) && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
734 xmlWrapStat = xmlWrapStatUtf8;
735 xmlWrapOpen = xmlWrapOpenUtf8;
737 xmlWrapGzOpen = xmlWrapGzOpenUtf8;
740 xmlWrapStat = xmlWrapStatNative;
741 xmlWrapOpen = xmlWrapOpenNative;
743 xmlWrapGzOpen = gzopen;
747 xmlPlatformIoInitialized = 1;
755 * @path: the path to check
757 * function checks to see if @path is a valid source
758 * (file, socket...) for XML.
760 * if stat is not available on the target machine,
761 * returns 1. if stat fails, returns 0 (if calling
762 * stat on the filename fails, it can't be right).
763 * if stat succeeds and the file is a directory,
764 * returns 2. otherwise returns 1.
768 xmlCheckFilename (const char *path)
771 struct stat stat_buffer;
777 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
778 if (xmlWrapStat(path, &stat_buffer) == -1)
781 if (stat(path, &stat_buffer) == -1)
785 if (S_ISDIR(stat_buffer.st_mode))
788 #endif /* HAVE_STAT */
799 * @context: the I/O context
800 * @buffer: where to drop data
801 * @len: number of bytes to read
803 * Read @len bytes to @buffer from the I/O channel.
805 * Returns the number of bytes written
808 xmlFdRead (void * context, char * buffer, int len) {
811 ret = read((int) (long) context, &buffer[0], len);
812 if (ret < 0) xmlIOErr(0, "read()");
816 #ifdef LIBXML_OUTPUT_ENABLED
819 * @context: the I/O context
820 * @buffer: where to get data
821 * @len: number of bytes to write
823 * Write @len bytes from @buffer to the I/O channel.
825 * Returns the number of bytes written
828 xmlFdWrite (void * context, const char * buffer, int len) {
832 ret = write((int) (long) context, &buffer[0], len);
833 if (ret < 0) xmlIOErr(0, "write()");
837 #endif /* LIBXML_OUTPUT_ENABLED */
841 * @context: the I/O context
843 * Close an I/O channel
845 * Returns 0 in case of success and error code otherwise
848 xmlFdClose (void * context) {
850 ret = close((int) (long) context);
851 if (ret < 0) xmlIOErr(0, "close()");
857 * @filename: the URI for matching
861 * Returns 1 if matches, 0 otherwise
864 xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
870 * @filename: the URI for matching
872 * input from FILE *, supports compressed input
873 * if @filename is " " then the standard input is used
875 * Returns an I/O context or NULL in case of error
878 xmlFileOpen_real (const char *filename) {
879 const char *path = NULL;
882 if (filename == NULL)
885 if (!strcmp(filename, "-")) {
890 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
891 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
892 path = &filename[17];
894 path = &filename[16];
896 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
897 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
902 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
903 /* lots of generators seems to lazy to read RFC 1738 */
904 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
914 if (!xmlCheckFilename(path))
917 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
918 fd = xmlWrapOpen(path, 0);
920 fd = fopen(path, "r");
922 if (fd == NULL) xmlIOErr(0, path);
928 * @filename: the URI for matching
930 * Wrapper around xmlFileOpen_real that try it with an unescaped
931 * version of @filename, if this fails fallback to @filename
933 * Returns a handler or NULL in case or failure
936 xmlFileOpen (const char *filename) {
940 retval = xmlFileOpen_real(filename);
941 if (retval == NULL) {
942 unescaped = xmlURIUnescapeString(filename, 0, NULL);
943 if (unescaped != NULL) {
944 retval = xmlFileOpen_real(unescaped);
952 #ifdef LIBXML_OUTPUT_ENABLED
955 * @filename: the URI for matching
957 * output to from FILE *,
958 * if @filename is "-" then the standard output is used
960 * Returns an I/O context or NULL in case of error
963 xmlFileOpenW (const char *filename) {
964 const char *path = NULL;
967 if (!strcmp(filename, "-")) {
972 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
973 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
974 path = &filename[17];
976 path = &filename[16];
978 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
979 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
990 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
991 fd = xmlWrapOpen(path, 1);
993 fd = fopen(path, "wb");
996 if (fd == NULL) xmlIOErr(0, path);
999 #endif /* LIBXML_OUTPUT_ENABLED */
1003 * @context: the I/O context
1004 * @buffer: where to drop data
1005 * @len: number of bytes to write
1007 * Read @len bytes to @buffer from the I/O channel.
1009 * Returns the number of bytes written or < 0 in case of failure
1012 xmlFileRead (void * context, char * buffer, int len) {
1014 if ((context == NULL) || (buffer == NULL))
1016 ret = fread(&buffer[0], 1, len, (FILE *) context);
1017 if (ret < 0) xmlIOErr(0, "fread()");
1021 #ifdef LIBXML_OUTPUT_ENABLED
1024 * @context: the I/O context
1025 * @buffer: where to drop data
1026 * @len: number of bytes to write
1028 * Write @len bytes from @buffer to the I/O channel.
1030 * Returns the number of bytes written
1033 xmlFileWrite (void * context, const char * buffer, int len) {
1036 if ((context == NULL) || (buffer == NULL))
1038 items = fwrite(&buffer[0], len, 1, (FILE *) context);
1039 if ((items == 0) && (ferror((FILE *) context))) {
1040 xmlIOErr(0, "fwrite()");
1043 return(items * len);
1045 #endif /* LIBXML_OUTPUT_ENABLED */
1049 * @context: the I/O context
1051 * Close an I/O channel
1053 * Returns 0 or -1 in case of error
1056 xmlFileClose (void * context) {
1060 if (context == NULL)
1062 fil = (FILE *) context;
1063 if ((fil == stdout) || (fil == stderr)) {
1066 xmlIOErr(0, "fflush()");
1071 ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
1073 xmlIOErr(0, "fclose()");
1079 * @context: the I/O context
1081 * Flush an I/O channel
1084 xmlFileFlush (void * context) {
1087 if (context == NULL)
1089 ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
1091 xmlIOErr(0, "fflush()");
1095 #ifdef LIBXML_OUTPUT_ENABLED
1098 * @context: the xmlBuffer
1099 * @buffer: the data to write
1100 * @len: number of bytes to write
1102 * Write @len bytes from @buffer to the xml buffer
1104 * Returns the number of bytes written
1107 xmlBufferWrite (void * context, const char * buffer, int len) {
1110 ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
1118 /************************************************************************
1120 * I/O for compressed file accesses *
1122 ************************************************************************/
1125 * @filename: the URI for matching
1127 * input from compressed file test
1129 * Returns 1 if matches, 0 otherwise
1132 xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
1137 * xmlGzfileOpen_real:
1138 * @filename: the URI for matching
1140 * input from compressed file open
1141 * if @filename is " " then the standard input is used
1143 * Returns an I/O context or NULL in case of error
1146 xmlGzfileOpen_real (const char *filename) {
1147 const char *path = NULL;
1150 if (!strcmp(filename, "-")) {
1151 fd = gzdopen(dup(0), "rb");
1152 return((void *) fd);
1155 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
1156 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1157 path = &filename[17];
1159 path = &filename[16];
1161 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1162 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1163 path = &filename[8];
1165 path = &filename[7];
1172 if (!xmlCheckFilename(path))
1175 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1176 fd = xmlWrapGzOpen(path, "rb");
1178 fd = gzopen(path, "rb");
1180 return((void *) fd);
1185 * @filename: the URI for matching
1187 * Wrapper around xmlGzfileOpen if the open fais, it will
1188 * try to unescape @filename
1191 xmlGzfileOpen (const char *filename) {
1195 retval = xmlGzfileOpen_real(filename);
1196 if (retval == NULL) {
1197 unescaped = xmlURIUnescapeString(filename, 0, NULL);
1198 if (unescaped != NULL) {
1199 retval = xmlGzfileOpen_real(unescaped);
1206 #ifdef LIBXML_OUTPUT_ENABLED
1209 * @filename: the URI for matching
1210 * @compression: the compression factor (0 - 9 included)
1212 * input from compressed file open
1213 * if @filename is " " then the standard input is used
1215 * Returns an I/O context or NULL in case of error
1218 xmlGzfileOpenW (const char *filename, int compression) {
1219 const char *path = NULL;
1223 snprintf(mode, sizeof(mode), "wb%d", compression);
1224 if (!strcmp(filename, "-")) {
1225 fd = gzdopen(dup(1), mode);
1226 return((void *) fd);
1229 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
1230 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1231 path = &filename[17];
1233 path = &filename[16];
1235 else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1236 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
1237 path = &filename[8];
1239 path = &filename[7];
1247 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
1248 fd = xmlWrapGzOpen(path, mode);
1250 fd = gzopen(path, mode);
1252 return((void *) fd);
1254 #endif /* LIBXML_OUTPUT_ENABLED */
1258 * @context: the I/O context
1259 * @buffer: where to drop data
1260 * @len: number of bytes to write
1262 * Read @len bytes to @buffer from the compressed I/O channel.
1264 * Returns the number of bytes written
1267 xmlGzfileRead (void * context, char * buffer, int len) {
1270 ret = gzread((gzFile) context, &buffer[0], len);
1271 if (ret < 0) xmlIOErr(0, "gzread()");
1275 #ifdef LIBXML_OUTPUT_ENABLED
1278 * @context: the I/O context
1279 * @buffer: where to drop data
1280 * @len: number of bytes to write
1282 * Write @len bytes from @buffer to the compressed I/O channel.
1284 * Returns the number of bytes written
1287 xmlGzfileWrite (void * context, const char * buffer, int len) {
1290 ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
1291 if (ret < 0) xmlIOErr(0, "gzwrite()");
1294 #endif /* LIBXML_OUTPUT_ENABLED */
1298 * @context: the I/O context
1300 * Close a compressed I/O channel
1303 xmlGzfileClose (void * context) {
1306 ret = (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
1307 if (ret < 0) xmlIOErr(0, "gzclose()");
1310 #endif /* HAVE_ZLIB_H */
1313 /************************************************************************
1315 * I/O for compressed file accesses *
1317 ************************************************************************/
1321 * @filename: the URI for matching
1323 * input from compressed file test
1325 * Returns 1 if matches, 0 otherwise
1328 xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
1333 * xmlXzFileOpen_real:
1334 * @filename: the URI for matching
1336 * input from compressed file open
1337 * if @filename is " " then the standard input is used
1339 * Returns an I/O context or NULL in case of error
1342 xmlXzfileOpen_real (const char *filename) {
1343 const char *path = NULL;
1346 if (!strcmp(filename, "-")) {
1347 fd = __libxml2_xzdopen(dup(0), "rb");
1348 return((void *) fd);
1351 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
1352 path = &filename[16];
1353 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
1354 path = &filename[7];
1355 } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
1356 /* lots of generators seems to lazy to read RFC 1738 */
1357 path = &filename[5];
1363 if (!xmlCheckFilename(path))
1366 fd = __libxml2_xzopen(path, "rb");
1367 return((void *) fd);
1372 * @filename: the URI for matching
1374 * Wrapper around xmlXzfileOpen_real that try it with an unescaped
1375 * version of @filename, if this fails fallback to @filename
1377 * Returns a handler or NULL in case or failure
1380 xmlXzfileOpen (const char *filename) {
1384 retval = xmlXzfileOpen_real(filename);
1385 if (retval == NULL) {
1386 unescaped = xmlURIUnescapeString(filename, 0, NULL);
1387 if (unescaped != NULL) {
1388 retval = xmlXzfileOpen_real(unescaped);
1398 * @context: the I/O context
1399 * @buffer: where to drop data
1400 * @len: number of bytes to write
1402 * Read @len bytes to @buffer from the compressed I/O channel.
1404 * Returns the number of bytes written
1407 xmlXzfileRead (void * context, char * buffer, int len) {
1410 ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
1411 if (ret < 0) xmlIOErr(0, "xzread()");
1417 * @context: the I/O context
1419 * Close a compressed I/O channel
1422 xmlXzfileClose (void * context) {
1425 ret = (__libxml2_xzclose((xzFile) context) == LZMA_OK ) ? 0 : -1;
1426 if (ret < 0) xmlIOErr(0, "xzclose()");
1429 #endif /* HAVE_LZMA_H */
1431 #ifdef LIBXML_HTTP_ENABLED
1432 /************************************************************************
1434 * I/O for HTTP file accesses *
1436 ************************************************************************/
1438 #ifdef LIBXML_OUTPUT_ENABLED
1439 typedef struct xmlIOHTTPWriteCtxt_
1447 } xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
1451 #define DFLT_WBITS ( -15 )
1452 #define DFLT_MEM_LVL ( 8 )
1453 #define GZ_MAGIC1 ( 0x1f )
1454 #define GZ_MAGIC2 ( 0x8b )
1455 #define LXML_ZLIB_OS_CODE ( 0x03 )
1456 #define INIT_HTTP_BUFF_SIZE ( 32768 )
1457 #define DFLT_ZLIB_RATIO ( 5 )
1460 ** Data structure and functions to work with sending compressed data
1464 typedef struct xmlZMemBuff_
1469 unsigned char * zbuff;
1472 } xmlZMemBuff, *xmlZMemBuffPtr;
1475 * append_reverse_ulong
1476 * @buff: Compressed memory buffer
1477 * @data: Unsigned long to append
1479 * Append a unsigned long in reverse byte order to the end of the
1483 append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
1491 ** This is plagiarized from putLong in gzio.c (zlib source) where
1492 ** the number "4" is hardcoded. If zlib is ever patched to
1493 ** support 64 bit file sizes, this code would need to be patched
1497 for ( idx = 0; idx < 4; idx++ ) {
1498 *buff->zctrl.next_out = ( data & 0xff );
1500 buff->zctrl.next_out++;
1509 * @buff: The memory buffer context to clear
1511 * Release all the resources associated with the compressed memory buffer.
1514 xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
1523 xmlFree( buff->zbuff );
1525 z_err = deflateEnd( &buff->zctrl );
1526 if ( z_err != Z_OK )
1527 xmlGenericError( xmlGenericErrorContext,
1528 "xmlFreeZMemBuff: Error releasing zlib context: %d\n",
1531 deflateEnd( &buff->zctrl );
1540 *@compression: Compression value to use
1542 * Create a memory buffer to hold the compressed XML document. The
1543 * compressed document in memory will end up being identical to what
1544 * would be created if gzopen/gzwrite/gzclose were being used to
1545 * write the document to disk. The code for the header/trailer data to
1546 * the compression is plagiarized from the zlib source files.
1549 xmlCreateZMemBuff( int compression ) {
1553 xmlZMemBuffPtr buff = NULL;
1555 if ( ( compression < 1 ) || ( compression > 9 ) )
1558 /* Create the control and data areas */
1560 buff = xmlMalloc( sizeof( xmlZMemBuff ) );
1561 if ( buff == NULL ) {
1562 xmlIOErrMemory("creating buffer context");
1566 (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
1567 buff->size = INIT_HTTP_BUFF_SIZE;
1568 buff->zbuff = xmlMalloc( buff->size );
1569 if ( buff->zbuff == NULL ) {
1570 xmlFreeZMemBuff( buff );
1571 xmlIOErrMemory("creating buffer");
1575 z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
1576 DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
1577 if ( z_err != Z_OK ) {
1579 xmlFreeZMemBuff( buff );
1581 xmlStrPrintf(msg, 500,
1582 (const xmlChar *) "xmlCreateZMemBuff: %s %d\n",
1583 "Error initializing compression context. ZLIB error:",
1585 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1589 /* Set the header data. The CRC will be needed for the trailer */
1590 buff->crc = crc32( 0L, NULL, 0 );
1591 hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
1592 "%c%c%c%c%c%c%c%c%c%c",
1593 GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
1594 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
1595 buff->zctrl.next_out = buff->zbuff + hdr_lgth;
1596 buff->zctrl.avail_out = buff->size - hdr_lgth;
1603 * @buff: Buffer used to compress and consolidate data.
1604 * @ext_amt: Number of bytes to extend the buffer.
1606 * Extend the internal buffer used to store the compressed data by the
1609 * Returns 0 on success or -1 on failure to extend the buffer. On failure
1610 * the original buffer still exists at the original size.
1613 xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
1619 unsigned char * tmp_ptr = NULL;
1624 else if ( ext_amt == 0 )
1627 cur_used = buff->zctrl.next_out - buff->zbuff;
1628 new_size = buff->size + ext_amt;
1631 if ( cur_used > new_size )
1632 xmlGenericError( xmlGenericErrorContext,
1633 "xmlZMemBuffExtend: %s\n%s %d bytes.\n",
1634 "Buffer overwrite detected during compressed memory",
1635 "buffer extension. Overflowed by",
1636 (cur_used - new_size ) );
1639 tmp_ptr = xmlRealloc( buff->zbuff, new_size );
1640 if ( tmp_ptr != NULL ) {
1642 buff->size = new_size;
1643 buff->zbuff = tmp_ptr;
1644 buff->zctrl.next_out = tmp_ptr + cur_used;
1645 buff->zctrl.avail_out = new_size - cur_used;
1649 xmlStrPrintf(msg, 500,
1650 (const xmlChar *) "xmlZMemBuffExtend: %s %lu bytes.\n",
1651 "Allocation failure extending output buffer to",
1653 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1661 * @buff: Buffer used to compress and consolidate data
1662 * @src: Uncompressed source content to append to buffer
1663 * @len: Length of source data to append to buffer
1665 * Compress and append data to the internal buffer. The data buffer
1666 * will be expanded if needed to store the additional data.
1668 * Returns the number of bytes appended to the buffer or -1 on error.
1671 xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
1676 if ( ( buff == NULL ) || ( src == NULL ) )
1679 buff->zctrl.avail_in = len;
1680 buff->zctrl.next_in = (unsigned char *)src;
1681 while ( buff->zctrl.avail_in > 0 ) {
1683 ** Extend the buffer prior to deflate call if a reasonable amount
1684 ** of output buffer space is not available.
1686 min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
1687 if ( buff->zctrl.avail_out <= min_accept ) {
1688 if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1692 z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
1693 if ( z_err != Z_OK ) {
1695 xmlStrPrintf(msg, 500,
1696 (const xmlChar *) "xmlZMemBuffAppend: %s %d %s - %d",
1697 "Compression error while appending",
1698 len, "bytes to buffer. ZLIB error", z_err );
1699 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1704 buff->crc = crc32( buff->crc, (unsigned char *)src, len );
1710 * xmlZMemBuffGetContent
1711 * @buff: Compressed memory content buffer
1712 * @data_ref: Pointer reference to point to compressed content
1714 * Flushes the compression buffers, appends gzip file trailers and
1715 * returns the compressed content and length of the compressed data.
1716 * NOTE: The gzip trailer code here is plagiarized from zlib source.
1718 * Returns the length of the compressed data or -1 on error.
1721 xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
1726 if ( ( buff == NULL ) || ( data_ref == NULL ) )
1729 /* Need to loop until compression output buffers are flushed */
1733 z_err = deflate( &buff->zctrl, Z_FINISH );
1734 if ( z_err == Z_OK ) {
1735 /* In this case Z_OK means more buffer space needed */
1737 if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
1741 while ( z_err == Z_OK );
1743 /* If the compression state is not Z_STREAM_END, some error occurred */
1745 if ( z_err == Z_STREAM_END ) {
1747 /* Need to append the gzip data trailer */
1749 if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
1750 if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
1755 ** For whatever reason, the CRC and length data are pushed out
1756 ** in reverse byte order. So a memcpy can't be used here.
1759 append_reverse_ulong( buff, buff->crc );
1760 append_reverse_ulong( buff, buff->zctrl.total_in );
1762 zlgth = buff->zctrl.next_out - buff->zbuff;
1763 *data_ref = (char *)buff->zbuff;
1768 xmlStrPrintf(msg, 500,
1769 (const xmlChar *) "xmlZMemBuffGetContent: %s - %d\n",
1770 "Error flushing zlib buffers. Error code", z_err );
1771 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1776 #endif /* LIBXML_OUTPUT_ENABLED */
1777 #endif /* HAVE_ZLIB_H */
1779 #ifdef LIBXML_OUTPUT_ENABLED
1781 * xmlFreeHTTPWriteCtxt
1782 * @ctxt: Context to cleanup
1784 * Free allocated memory and reclaim system resources.
1789 xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
1791 if ( ctxt->uri != NULL )
1792 xmlFree( ctxt->uri );
1794 if ( ctxt->doc_buff != NULL ) {
1797 if ( ctxt->compression > 0 ) {
1798 xmlFreeZMemBuff( ctxt->doc_buff );
1803 xmlOutputBufferClose( ctxt->doc_buff );
1810 #endif /* LIBXML_OUTPUT_ENABLED */
1815 * @filename: the URI for matching
1817 * check if the URI matches an HTTP one
1819 * Returns 1 if matches, 0 otherwise
1822 xmlIOHTTPMatch (const char *filename) {
1823 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
1830 * @filename: the URI for matching
1832 * open an HTTP I/O channel
1834 * Returns an I/O context or NULL in case of error
1837 xmlIOHTTPOpen (const char *filename) {
1838 return(xmlNanoHTTPOpen(filename, NULL));
1841 #ifdef LIBXML_OUTPUT_ENABLED
1844 * @post_uri: The destination URI for the document
1845 * @compression: The compression desired for the document.
1847 * Open a temporary buffer to collect the document for a subsequent HTTP POST
1848 * request. Non-static as is called from the output buffer creation routine.
1850 * Returns an I/O context or NULL in case of error.
1854 xmlIOHTTPOpenW(const char *post_uri, int compression)
1857 xmlIOHTTPWriteCtxtPtr ctxt = NULL;
1859 if (post_uri == NULL)
1862 ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
1864 xmlIOErrMemory("creating HTTP output context");
1868 (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
1870 ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
1871 if (ctxt->uri == NULL) {
1872 xmlIOErrMemory("copying URI");
1873 xmlFreeHTTPWriteCtxt(ctxt);
1878 * ** Since the document length is required for an HTTP post,
1879 * ** need to put the document into a buffer. A memory buffer
1880 * ** is being used to avoid pushing the data to disk and back.
1884 if ((compression > 0) && (compression <= 9)) {
1886 ctxt->compression = compression;
1887 ctxt->doc_buff = xmlCreateZMemBuff(compression);
1891 /* Any character conversions should have been done before this */
1893 ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
1896 if (ctxt->doc_buff == NULL) {
1897 xmlFreeHTTPWriteCtxt(ctxt);
1903 #endif /* LIBXML_OUTPUT_ENABLED */
1905 #ifdef LIBXML_OUTPUT_ENABLED
1907 * xmlIOHTTPDfltOpenW
1908 * @post_uri: The destination URI for this document.
1910 * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
1911 * HTTP post command. This function should generally not be used as
1912 * the open callback is short circuited in xmlOutputBufferCreateFile.
1914 * Returns a pointer to the new IO context.
1917 xmlIOHTTPDfltOpenW( const char * post_uri ) {
1918 return ( xmlIOHTTPOpenW( post_uri, 0 ) );
1920 #endif /* LIBXML_OUTPUT_ENABLED */
1924 * @context: the I/O context
1925 * @buffer: where to drop data
1926 * @len: number of bytes to write
1928 * Read @len bytes to @buffer from the I/O channel.
1930 * Returns the number of bytes written
1933 xmlIOHTTPRead(void * context, char * buffer, int len) {
1934 if ((buffer == NULL) || (len < 0)) return(-1);
1935 return(xmlNanoHTTPRead(context, &buffer[0], len));
1938 #ifdef LIBXML_OUTPUT_ENABLED
1941 * @context: previously opened writing context
1942 * @buffer: data to output to temporary buffer
1943 * @len: bytes to output
1945 * Collect data from memory buffer into a temporary file for later
1948 * Returns number of bytes written.
1952 xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
1954 xmlIOHTTPWriteCtxtPtr ctxt = context;
1956 if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
1961 /* Use gzwrite or fwrite as previously setup in the open call */
1964 if ( ctxt->compression > 0 )
1965 len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
1969 len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
1973 xmlStrPrintf(msg, 500,
1974 (const xmlChar *) "xmlIOHTTPWrite: %s\n%s '%s'.\n",
1975 "Error appending to internal buffer.",
1976 "Error sending document to URI",
1978 xmlIOErr(XML_IO_WRITE, (const char *) msg);
1984 #endif /* LIBXML_OUTPUT_ENABLED */
1989 * @context: the I/O context
1991 * Close an HTTP I/O channel
1996 xmlIOHTTPClose (void * context) {
1997 xmlNanoHTTPClose(context);
2001 #ifdef LIBXML_OUTPUT_ENABLED
2003 * xmlIOHTTCloseWrite
2004 * @context: The I/O context
2005 * @http_mthd: The HTTP method to be used when sending the data
2007 * Close the transmit HTTP I/O channel and actually send the data.
2010 xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
2014 int content_lgth = 0;
2015 xmlIOHTTPWriteCtxtPtr ctxt = context;
2017 char * http_content = NULL;
2018 char * content_encoding = NULL;
2019 char * content_type = (char *) "text/xml";
2020 void * http_ctxt = NULL;
2022 if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
2025 /* Retrieve the content from the appropriate buffer */
2029 if ( ctxt->compression > 0 ) {
2030 content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
2031 content_encoding = (char *) "Content-Encoding: gzip";
2036 /* Pull the data out of the memory output buffer */
2038 xmlOutputBufferPtr dctxt = ctxt->doc_buff;
2039 http_content = (char *)dctxt->buffer->content;
2040 content_lgth = dctxt->buffer->use;
2043 if ( http_content == NULL ) {
2045 xmlStrPrintf(msg, 500,
2046 (const xmlChar *) "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n",
2047 "Error retrieving content.\nUnable to",
2048 http_mthd, "data to URI", ctxt->uri );
2049 xmlIOErr(XML_IO_WRITE, (const char *) msg);
2054 http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
2055 &content_type, content_encoding,
2058 if ( http_ctxt != NULL ) {
2060 /* If testing/debugging - dump reply with request content */
2062 FILE * tst_file = NULL;
2063 char buffer[ 4096 ];
2064 char * dump_name = NULL;
2067 xmlGenericError( xmlGenericErrorContext,
2068 "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n",
2069 http_mthd, ctxt->uri,
2070 xmlNanoHTTPReturnCode( http_ctxt ) );
2073 ** Since either content or reply may be gzipped,
2074 ** dump them to separate files instead of the
2075 ** standard error context.
2078 dump_name = tempnam( NULL, "lxml" );
2079 if ( dump_name != NULL ) {
2080 (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
2082 tst_file = fopen( buffer, "wb" );
2083 if ( tst_file != NULL ) {
2084 xmlGenericError( xmlGenericErrorContext,
2085 "Transmitted content saved in file: %s\n", buffer );
2087 fwrite( http_content, sizeof( char ),
2088 content_lgth, tst_file );
2092 (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
2093 tst_file = fopen( buffer, "wb" );
2094 if ( tst_file != NULL ) {
2095 xmlGenericError( xmlGenericErrorContext,
2096 "Reply content saved in file: %s\n", buffer );
2099 while ( (avail = xmlNanoHTTPRead( http_ctxt,
2100 buffer, sizeof( buffer ) )) > 0 ) {
2102 fwrite( buffer, sizeof( char ), avail, tst_file );
2110 #endif /* DEBUG_HTTP */
2112 http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
2113 if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
2117 xmlStrPrintf(msg, 500,
2118 (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
2119 http_mthd, content_lgth,
2120 "bytes to URI", ctxt->uri,
2121 "failed. HTTP return code:", http_rtn );
2122 xmlIOErr(XML_IO_WRITE, (const char *) msg);
2125 xmlNanoHTTPClose( http_ctxt );
2126 xmlFree( content_type );
2130 /* Final cleanups */
2132 xmlFreeHTTPWriteCtxt( ctxt );
2134 return ( close_rc );
2140 * @context: The I/O context
2142 * Close the transmit HTTP I/O channel and actually send data using a PUT
2146 xmlIOHTTPClosePut( void * ctxt ) {
2147 return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
2152 * xmlIOHTTPClosePost
2154 * @context: The I/O context
2156 * Close the transmit HTTP I/O channel and actually send data using a POST
2160 xmlIOHTTPClosePost( void * ctxt ) {
2161 return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
2163 #endif /* LIBXML_OUTPUT_ENABLED */
2165 #endif /* LIBXML_HTTP_ENABLED */
2167 #ifdef LIBXML_FTP_ENABLED
2168 /************************************************************************
2170 * I/O for FTP file accesses *
2172 ************************************************************************/
2175 * @filename: the URI for matching
2177 * check if the URI matches an FTP one
2179 * Returns 1 if matches, 0 otherwise
2182 xmlIOFTPMatch (const char *filename) {
2183 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
2190 * @filename: the URI for matching
2192 * open an FTP I/O channel
2194 * Returns an I/O context or NULL in case of error
2197 xmlIOFTPOpen (const char *filename) {
2198 return(xmlNanoFTPOpen(filename));
2203 * @context: the I/O context
2204 * @buffer: where to drop data
2205 * @len: number of bytes to write
2207 * Read @len bytes to @buffer from the I/O channel.
2209 * Returns the number of bytes written
2212 xmlIOFTPRead(void * context, char * buffer, int len) {
2213 if ((buffer == NULL) || (len < 0)) return(-1);
2214 return(xmlNanoFTPRead(context, &buffer[0], len));
2219 * @context: the I/O context
2221 * Close an FTP I/O channel
2226 xmlIOFTPClose (void * context) {
2227 return ( xmlNanoFTPClose(context) );
2229 #endif /* LIBXML_FTP_ENABLED */
2233 * xmlRegisterInputCallbacks:
2234 * @matchFunc: the xmlInputMatchCallback
2235 * @openFunc: the xmlInputOpenCallback
2236 * @readFunc: the xmlInputReadCallback
2237 * @closeFunc: the xmlInputCloseCallback
2239 * Register a new set of I/O callback for handling parser input.
2241 * Returns the registered handler number or -1 in case of error
2244 xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2245 xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2246 xmlInputCloseCallback closeFunc) {
2247 if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2250 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2251 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2252 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2253 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2254 xmlInputCallbackInitialized = 1;
2255 return(xmlInputCallbackNr++);
2258 #ifdef LIBXML_OUTPUT_ENABLED
2260 * xmlRegisterOutputCallbacks:
2261 * @matchFunc: the xmlOutputMatchCallback
2262 * @openFunc: the xmlOutputOpenCallback
2263 * @writeFunc: the xmlOutputWriteCallback
2264 * @closeFunc: the xmlOutputCloseCallback
2266 * Register a new set of I/O callback for handling output.
2268 * Returns the registered handler number or -1 in case of error
2271 xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2272 xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2273 xmlOutputCloseCallback closeFunc) {
2274 if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2277 xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2278 xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2279 xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2280 xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2281 xmlOutputCallbackInitialized = 1;
2282 return(xmlOutputCallbackNr++);
2284 #endif /* LIBXML_OUTPUT_ENABLED */
2287 * xmlRegisterDefaultInputCallbacks:
2289 * Registers the default compiled-in I/O handlers.
2292 xmlRegisterDefaultInputCallbacks(void) {
2293 if (xmlInputCallbackInitialized)
2296 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2297 xmlInitPlatformSpecificIo();
2300 xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
2301 xmlFileRead, xmlFileClose);
2303 xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2304 xmlGzfileRead, xmlGzfileClose);
2305 #endif /* HAVE_ZLIB_H */
2307 xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen,
2308 xmlXzfileRead, xmlXzfileClose);
2309 #endif /* HAVE_ZLIB_H */
2311 #ifdef LIBXML_HTTP_ENABLED
2312 xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
2313 xmlIOHTTPRead, xmlIOHTTPClose);
2314 #endif /* LIBXML_HTTP_ENABLED */
2316 #ifdef LIBXML_FTP_ENABLED
2317 xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2318 xmlIOFTPRead, xmlIOFTPClose);
2319 #endif /* LIBXML_FTP_ENABLED */
2320 xmlInputCallbackInitialized = 1;
2323 #ifdef LIBXML_OUTPUT_ENABLED
2325 * xmlRegisterDefaultOutputCallbacks:
2327 * Registers the default compiled-in I/O handlers.
2330 xmlRegisterDefaultOutputCallbacks (void) {
2331 if (xmlOutputCallbackInitialized)
2334 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2335 xmlInitPlatformSpecificIo();
2338 xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
2339 xmlFileWrite, xmlFileClose);
2341 #ifdef LIBXML_HTTP_ENABLED
2342 xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2343 xmlIOHTTPWrite, xmlIOHTTPClosePut);
2346 /*********************************
2347 No way a-priori to distinguish between gzipped files from
2348 uncompressed ones except opening if existing then closing
2349 and saving with same compression ratio ... a pain.
2352 xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
2353 xmlGzfileWrite, xmlGzfileClose);
2357 #ifdef LIBXML_FTP_ENABLED
2358 xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
2359 xmlIOFTPWrite, xmlIOFTPClose);
2361 **********************************/
2362 xmlOutputCallbackInitialized = 1;
2365 #ifdef LIBXML_HTTP_ENABLED
2367 * xmlRegisterHTTPPostCallbacks:
2369 * By default, libxml submits HTTP output requests using the "PUT" method.
2370 * Calling this method changes the HTTP output method to use the "POST"
2375 xmlRegisterHTTPPostCallbacks( void ) {
2377 /* Register defaults if not done previously */
2379 if ( xmlOutputCallbackInitialized == 0 )
2380 xmlRegisterDefaultOutputCallbacks( );
2382 xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
2383 xmlIOHTTPWrite, xmlIOHTTPClosePost);
2387 #endif /* LIBXML_OUTPUT_ENABLED */
2390 * xmlAllocParserInputBuffer:
2391 * @enc: the charset encoding if known
2393 * Create a buffered parser input for progressive parsing
2395 * Returns the new parser input or NULL
2397 xmlParserInputBufferPtr
2398 xmlAllocParserInputBuffer(xmlCharEncoding enc) {
2399 xmlParserInputBufferPtr ret;
2401 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
2403 xmlIOErrMemory("creating input buffer");
2406 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
2407 ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
2408 if (ret->buffer == NULL) {
2412 ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
2413 ret->encoder = xmlGetCharEncodingHandler(enc);
2414 if (ret->encoder != NULL)
2415 ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
2418 ret->readcallback = NULL;
2419 ret->closecallback = NULL;
2420 ret->context = NULL;
2421 ret->compressed = -1;
2422 ret->rawconsumed = 0;
2427 #ifdef LIBXML_OUTPUT_ENABLED
2429 * xmlAllocOutputBuffer:
2430 * @encoder: the encoding converter or NULL
2432 * Create a buffered parser output
2434 * Returns the new parser output or NULL
2437 xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
2438 xmlOutputBufferPtr ret;
2440 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2442 xmlIOErrMemory("creating output buffer");
2445 memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2446 ret->buffer = xmlBufferCreate();
2447 if (ret->buffer == NULL) {
2452 /* try to avoid a performance problem with Windows realloc() */
2453 if (ret->buffer->alloc == XML_BUFFER_ALLOC_EXACT)
2454 ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
2456 ret->encoder = encoder;
2457 if (encoder != NULL) {
2458 ret->conv = xmlBufferCreateSize(4000);
2459 if (ret->conv == NULL) {
2465 * This call is designed to initiate the encoder state
2467 xmlCharEncOutFunc(encoder, ret->conv, NULL);
2470 ret->writecallback = NULL;
2471 ret->closecallback = NULL;
2472 ret->context = NULL;
2479 * xmlAllocOutputBufferInternal:
2480 * @encoder: the encoding converter or NULL
2482 * Create a buffered parser output
2484 * Returns the new parser output or NULL
2487 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
2488 xmlOutputBufferPtr ret;
2490 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2492 xmlIOErrMemory("creating output buffer");
2495 memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
2496 ret->buffer = xmlBufferCreate();
2497 if (ret->buffer == NULL) {
2504 * For conversion buffers we use the special IO handling
2505 * We don't do that from the exported API to avoid confusing
2508 ret->buffer->alloc = XML_BUFFER_ALLOC_IO;
2509 ret->buffer->contentIO = ret->buffer->content;
2511 ret->encoder = encoder;
2512 if (encoder != NULL) {
2513 ret->conv = xmlBufferCreateSize(4000);
2514 if (ret->conv == NULL) {
2520 * This call is designed to initiate the encoder state
2522 xmlCharEncOutFunc(encoder, ret->conv, NULL);
2525 ret->writecallback = NULL;
2526 ret->closecallback = NULL;
2527 ret->context = NULL;
2533 #endif /* LIBXML_OUTPUT_ENABLED */
2536 * xmlFreeParserInputBuffer:
2537 * @in: a buffered parser input
2539 * Free up the memory used by a buffered parser input
2542 xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
2543 if (in == NULL) return;
2546 xmlBufferFree(in->raw);
2549 if (in->encoder != NULL) {
2550 xmlCharEncCloseFunc(in->encoder);
2552 if (in->closecallback != NULL) {
2553 in->closecallback(in->context);
2555 if (in->buffer != NULL) {
2556 xmlBufferFree(in->buffer);
2563 #ifdef LIBXML_OUTPUT_ENABLED
2565 * xmlOutputBufferClose:
2566 * @out: a buffered output
2568 * flushes and close the output I/O channel
2569 * and free up all the associated resources
2571 * Returns the number of byte written or -1 in case of error.
2574 xmlOutputBufferClose(xmlOutputBufferPtr out)
2581 if (out->writecallback != NULL)
2582 xmlOutputBufferFlush(out);
2583 if (out->closecallback != NULL) {
2584 err_rc = out->closecallback(out->context);
2586 written = out->written;
2588 xmlBufferFree(out->conv);
2591 if (out->encoder != NULL) {
2592 xmlCharEncCloseFunc(out->encoder);
2594 if (out->buffer != NULL) {
2595 xmlBufferFree(out->buffer);
2602 return ((err_rc == 0) ? written : err_rc);
2604 #endif /* LIBXML_OUTPUT_ENABLED */
2606 xmlParserInputBufferPtr
2607 __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2608 xmlParserInputBufferPtr ret;
2610 void *context = NULL;
2612 if (xmlInputCallbackInitialized == 0)
2613 xmlRegisterDefaultInputCallbacks();
2615 if (URI == NULL) return(NULL);
2618 * Try to find one of the input accept method accepting that scheme
2619 * Go in reverse to give precedence to user defined handlers.
2621 if (context == NULL) {
2622 for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
2623 if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
2624 (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
2625 context = xmlInputCallbackTable[i].opencallback(URI);
2626 if (context != NULL) {
2632 if (context == NULL) {
2637 * Allocate the Input buffer front-end.
2639 ret = xmlAllocParserInputBuffer(enc);
2641 ret->context = context;
2642 ret->readcallback = xmlInputCallbackTable[i].readcallback;
2643 ret->closecallback = xmlInputCallbackTable[i].closecallback;
2645 if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
2646 (strcmp(URI, "-") != 0)) {
2647 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
2648 ret->compressed = !gzdirect(context);
2650 if (((z_stream *)context)->avail_in > 4) {
2651 char *cptr, buff4[4];
2652 cptr = (char *) ((z_stream *)context)->next_in;
2653 if (gzread(context, buff4, 4) == 4) {
2654 if (strncmp(buff4, cptr, 4) == 0)
2655 ret->compressed = 0;
2657 ret->compressed = 1;
2666 xmlInputCallbackTable[i].closecallback (context);
2672 * xmlParserInputBufferCreateFilename:
2673 * @URI: a C string containing the URI or filename
2674 * @enc: the charset encoding if known
2676 * Create a buffered parser input for the progressive parsing of a file
2677 * If filename is "-' then we use stdin as the input.
2678 * Automatic support for ZLIB/Compress compressed document is provided
2679 * by default if found at compile-time.
2680 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
2682 * Returns the new parser input or NULL
2684 xmlParserInputBufferPtr
2685 xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
2686 if ((xmlParserInputBufferCreateFilenameValue)) {
2687 return xmlParserInputBufferCreateFilenameValue(URI, enc);
2689 return __xmlParserInputBufferCreateFilename(URI, enc);
2692 #ifdef LIBXML_OUTPUT_ENABLED
2694 __xmlOutputBufferCreateFilename(const char *URI,
2695 xmlCharEncodingHandlerPtr encoder,
2696 int compression ATTRIBUTE_UNUSED) {
2697 xmlOutputBufferPtr ret;
2700 void *context = NULL;
2701 char *unescaped = NULL;
2703 int is_file_uri = 1;
2706 if (xmlOutputCallbackInitialized == 0)
2707 xmlRegisterDefaultOutputCallbacks();
2709 if (URI == NULL) return(NULL);
2711 puri = xmlParseURI(URI);
2714 if ((puri->scheme != NULL) &&
2715 (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
2719 * try to limit the damages of the URI unescaping code.
2721 if ((puri->scheme == NULL) ||
2722 (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
2723 unescaped = xmlURIUnescapeString(URI, 0, NULL);
2728 * Try to find one of the output accept method accepting that scheme
2729 * Go in reverse to give precedence to user defined handlers.
2730 * try with an unescaped version of the URI
2732 if (unescaped != NULL) {
2734 if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
2735 context = xmlGzfileOpenW(unescaped, compression);
2736 if (context != NULL) {
2737 ret = xmlAllocOutputBufferInternal(encoder);
2739 ret->context = context;
2740 ret->writecallback = xmlGzfileWrite;
2741 ret->closecallback = xmlGzfileClose;
2748 for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2749 if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2750 (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
2751 #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
2752 /* Need to pass compression parameter into HTTP open calls */
2753 if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2754 context = xmlIOHTTPOpenW(unescaped, compression);
2757 context = xmlOutputCallbackTable[i].opencallback(unescaped);
2758 if (context != NULL)
2766 * If this failed try with a non-escaped URI this may be a strange
2769 if (context == NULL) {
2771 if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
2772 context = xmlGzfileOpenW(URI, compression);
2773 if (context != NULL) {
2774 ret = xmlAllocOutputBufferInternal(encoder);
2776 ret->context = context;
2777 ret->writecallback = xmlGzfileWrite;
2778 ret->closecallback = xmlGzfileClose;
2784 for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
2785 if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
2786 (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
2787 #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
2788 /* Need to pass compression parameter into HTTP open calls */
2789 if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
2790 context = xmlIOHTTPOpenW(URI, compression);
2793 context = xmlOutputCallbackTable[i].opencallback(URI);
2794 if (context != NULL)
2800 if (context == NULL) {
2805 * Allocate the Output buffer front-end.
2807 ret = xmlAllocOutputBufferInternal(encoder);
2809 ret->context = context;
2810 ret->writecallback = xmlOutputCallbackTable[i].writecallback;
2811 ret->closecallback = xmlOutputCallbackTable[i].closecallback;
2817 * xmlOutputBufferCreateFilename:
2818 * @URI: a C string containing the URI or filename
2819 * @encoder: the encoding converter or NULL
2820 * @compression: the compression ration (0 none, 9 max).
2822 * Create a buffered output for the progressive saving of a file
2823 * If filename is "-' then we use stdout as the output.
2824 * Automatic support for ZLIB/Compress compressed document is provided
2825 * by default if found at compile-time.
2826 * TODO: currently if compression is set, the library only support
2827 * writing to a local file.
2829 * Returns the new output or NULL
2832 xmlOutputBufferCreateFilename(const char *URI,
2833 xmlCharEncodingHandlerPtr encoder,
2834 int compression ATTRIBUTE_UNUSED) {
2835 if ((xmlOutputBufferCreateFilenameValue)) {
2836 return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
2838 return __xmlOutputBufferCreateFilename(URI, encoder, compression);
2840 #endif /* LIBXML_OUTPUT_ENABLED */
2843 * xmlParserInputBufferCreateFile:
2845 * @enc: the charset encoding if known
2847 * Create a buffered parser input for the progressive parsing of a FILE *
2850 * Returns the new parser input or NULL
2852 xmlParserInputBufferPtr
2853 xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
2854 xmlParserInputBufferPtr ret;
2856 if (xmlInputCallbackInitialized == 0)
2857 xmlRegisterDefaultInputCallbacks();
2859 if (file == NULL) return(NULL);
2861 ret = xmlAllocParserInputBuffer(enc);
2863 ret->context = file;
2864 ret->readcallback = xmlFileRead;
2865 ret->closecallback = xmlFileFlush;
2871 #ifdef LIBXML_OUTPUT_ENABLED
2873 * xmlOutputBufferCreateFile:
2875 * @encoder: the encoding converter or NULL
2877 * Create a buffered output for the progressive saving to a FILE *
2880 * Returns the new parser output or NULL
2883 xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
2884 xmlOutputBufferPtr ret;
2886 if (xmlOutputCallbackInitialized == 0)
2887 xmlRegisterDefaultOutputCallbacks();
2889 if (file == NULL) return(NULL);
2891 ret = xmlAllocOutputBufferInternal(encoder);
2893 ret->context = file;
2894 ret->writecallback = xmlFileWrite;
2895 ret->closecallback = xmlFileFlush;
2902 * xmlOutputBufferCreateBuffer:
2903 * @buffer: a xmlBufferPtr
2904 * @encoder: the encoding converter or NULL
2906 * Create a buffered output for the progressive saving to a xmlBuffer
2908 * Returns the new parser output or NULL
2911 xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
2912 xmlCharEncodingHandlerPtr encoder) {
2913 xmlOutputBufferPtr ret;
2915 if (buffer == NULL) return(NULL);
2917 ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
2919 (xmlOutputCloseCallback)
2920 NULL, (void *) buffer, encoder);
2925 #endif /* LIBXML_OUTPUT_ENABLED */
2928 * xmlParserInputBufferCreateFd:
2929 * @fd: a file descriptor number
2930 * @enc: the charset encoding if known
2932 * Create a buffered parser input for the progressive parsing for the input
2933 * from a file descriptor
2935 * Returns the new parser input or NULL
2937 xmlParserInputBufferPtr
2938 xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
2939 xmlParserInputBufferPtr ret;
2941 if (fd < 0) return(NULL);
2943 ret = xmlAllocParserInputBuffer(enc);
2945 ret->context = (void *) (long) fd;
2946 ret->readcallback = xmlFdRead;
2947 ret->closecallback = xmlFdClose;
2954 * xmlParserInputBufferCreateMem:
2955 * @mem: the memory input
2956 * @size: the length of the memory block
2957 * @enc: the charset encoding if known
2959 * Create a buffered parser input for the progressive parsing for the input
2960 * from a memory area.
2962 * Returns the new parser input or NULL
2964 xmlParserInputBufferPtr
2965 xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
2966 xmlParserInputBufferPtr ret;
2969 if (size <= 0) return(NULL);
2970 if (mem == NULL) return(NULL);
2972 ret = xmlAllocParserInputBuffer(enc);
2974 ret->context = (void *) mem;
2975 ret->readcallback = (xmlInputReadCallback) xmlNop;
2976 ret->closecallback = NULL;
2977 errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
2988 * xmlParserInputBufferCreateStatic:
2989 * @mem: the memory input
2990 * @size: the length of the memory block
2991 * @enc: the charset encoding if known
2993 * Create a buffered parser input for the progressive parsing for the input
2994 * from an immutable memory area. This will not copy the memory area to
2995 * the buffer, but the memory is expected to be available until the end of
2996 * the parsing, this is useful for example when using mmap'ed file.
2998 * Returns the new parser input or NULL
3000 xmlParserInputBufferPtr
3001 xmlParserInputBufferCreateStatic(const char *mem, int size,
3002 xmlCharEncoding enc) {
3003 xmlParserInputBufferPtr ret;
3005 if (size <= 0) return(NULL);
3006 if (mem == NULL) return(NULL);
3008 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
3010 xmlIOErrMemory("creating input buffer");
3013 memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
3014 ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size);
3015 if (ret->buffer == NULL) {
3019 ret->encoder = xmlGetCharEncodingHandler(enc);
3020 if (ret->encoder != NULL)
3021 ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
3024 ret->compressed = -1;
3025 ret->context = (void *) mem;
3026 ret->readcallback = NULL;
3027 ret->closecallback = NULL;
3032 #ifdef LIBXML_OUTPUT_ENABLED
3034 * xmlOutputBufferCreateFd:
3035 * @fd: a file descriptor number
3036 * @encoder: the encoding converter or NULL
3038 * Create a buffered output for the progressive saving
3039 * to a file descriptor
3041 * Returns the new parser output or NULL
3044 xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
3045 xmlOutputBufferPtr ret;
3047 if (fd < 0) return(NULL);
3049 ret = xmlAllocOutputBufferInternal(encoder);
3051 ret->context = (void *) (long) fd;
3052 ret->writecallback = xmlFdWrite;
3053 ret->closecallback = NULL;
3058 #endif /* LIBXML_OUTPUT_ENABLED */
3061 * xmlParserInputBufferCreateIO:
3062 * @ioread: an I/O read function
3063 * @ioclose: an I/O close function
3064 * @ioctx: an I/O handler
3065 * @enc: the charset encoding if known
3067 * Create a buffered parser input for the progressive parsing for the input
3068 * from an I/O handler
3070 * Returns the new parser input or NULL
3072 xmlParserInputBufferPtr
3073 xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
3074 xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
3075 xmlParserInputBufferPtr ret;
3077 if (ioread == NULL) return(NULL);
3079 ret = xmlAllocParserInputBuffer(enc);
3081 ret->context = (void *) ioctx;
3082 ret->readcallback = ioread;
3083 ret->closecallback = ioclose;
3089 #ifdef LIBXML_OUTPUT_ENABLED
3091 * xmlOutputBufferCreateIO:
3092 * @iowrite: an I/O write function
3093 * @ioclose: an I/O close function
3094 * @ioctx: an I/O handler
3095 * @encoder: the charset encoding if known
3097 * Create a buffered output for the progressive saving
3100 * Returns the new parser output or NULL
3103 xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
3104 xmlOutputCloseCallback ioclose, void *ioctx,
3105 xmlCharEncodingHandlerPtr encoder) {
3106 xmlOutputBufferPtr ret;
3108 if (iowrite == NULL) return(NULL);
3110 ret = xmlAllocOutputBufferInternal(encoder);
3112 ret->context = (void *) ioctx;
3113 ret->writecallback = iowrite;
3114 ret->closecallback = ioclose;
3119 #endif /* LIBXML_OUTPUT_ENABLED */
3122 * xmlParserInputBufferCreateFilenameDefault:
3123 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
3125 * Registers a callback for URI input file handling
3127 * Returns the old value of the registration function
3129 xmlParserInputBufferCreateFilenameFunc
3130 xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
3132 xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
3134 old = __xmlParserInputBufferCreateFilename;
3137 xmlParserInputBufferCreateFilenameValue = func;
3142 * xmlOutputBufferCreateFilenameDefault:
3143 * @func: function pointer to the new OutputBufferCreateFilenameFunc
3145 * Registers a callback for URI output file handling
3147 * Returns the old value of the registration function
3149 xmlOutputBufferCreateFilenameFunc
3150 xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
3152 xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
3153 #ifdef LIBXML_OUTPUT_ENABLED
3155 old = __xmlOutputBufferCreateFilename;
3158 xmlOutputBufferCreateFilenameValue = func;
3163 * xmlParserInputBufferPush:
3164 * @in: a buffered parser input
3165 * @len: the size in bytes of the array.
3166 * @buf: an char array
3168 * Push the content of the arry in the input buffer
3169 * This routine handle the I18N transcoding to internal UTF-8
3170 * This is used when operating the parser in progressive (push) mode.
3172 * Returns the number of chars read and stored in the buffer, or -1
3176 xmlParserInputBufferPush(xmlParserInputBufferPtr in,
3177 int len, const char *buf) {
3181 if (len < 0) return(0);
3182 if ((in == NULL) || (in->error)) return(-1);
3183 if (in->encoder != NULL) {
3187 * Store the data in the incoming raw buffer
3189 if (in->raw == NULL) {
3190 in->raw = xmlBufferCreate();
3192 ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
3197 * convert as much as possible to the parser reading buffer.
3200 nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
3202 xmlIOErr(XML_IO_ENCODER, NULL);
3203 in->error = XML_IO_ENCODER;
3206 in->rawconsumed += (use - in->raw->use);
3209 ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
3214 xmlGenericError(xmlGenericErrorContext,
3215 "I/O: pushed %d chars, buffer %d/%d\n",
3216 nbchars, in->buffer->use, in->buffer->size);
3224 * When reading from an Input channel indicated end of file or error
3225 * don't reread from it again.
3228 endOfInput (void * context ATTRIBUTE_UNUSED,
3229 char * buffer ATTRIBUTE_UNUSED,
3230 int len ATTRIBUTE_UNUSED) {
3235 * xmlParserInputBufferGrow:
3236 * @in: a buffered parser input
3237 * @len: indicative value of the amount of chars to read
3239 * Grow up the content of the input buffer, the old data are preserved
3240 * This routine handle the I18N transcoding to internal UTF-8
3241 * This routine is used when operating the parser in normal (pull) mode
3243 * TODO: one should be able to remove one extra copy by copying directly
3244 * onto in->buffer or in->raw
3246 * Returns the number of chars read and stored in the buffer, or -1
3250 xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
3251 char *buffer = NULL;
3255 unsigned int needSize;
3257 if ((in == NULL) || (in->error)) return(-1);
3258 if ((len <= MINLEN) && (len != 4))
3261 buffree = in->buffer->size - in->buffer->use;
3263 xmlIOErr(XML_IO_BUFFER_FULL, NULL);
3264 in->error = XML_IO_BUFFER_FULL;
3268 needSize = in->buffer->use + len + 1;
3269 if (needSize > in->buffer->size){
3270 if (!xmlBufferResize(in->buffer, needSize)){
3271 xmlIOErrMemory("growing input buffer");
3272 in->error = XML_ERR_NO_MEMORY;
3276 buffer = (char *)&in->buffer->content[in->buffer->use];
3279 * Call the read method for this I/O type.
3281 if (in->readcallback != NULL) {
3282 res = in->readcallback(in->context, &buffer[0], len);
3284 in->readcallback = endOfInput;
3286 xmlIOErr(XML_IO_NO_INPUT, NULL);
3287 in->error = XML_IO_NO_INPUT;
3294 if (in->encoder != NULL) {
3298 * Store the data in the incoming raw buffer
3300 if (in->raw == NULL) {
3301 in->raw = xmlBufferCreate();
3303 res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
3308 * convert as much as possible to the parser reading buffer.
3311 nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
3313 xmlIOErr(XML_IO_ENCODER, NULL);
3314 in->error = XML_IO_ENCODER;
3317 in->rawconsumed += (use - in->raw->use);
3320 in->buffer->use += nbchars;
3321 buffer[nbchars] = 0;
3324 xmlGenericError(xmlGenericErrorContext,
3325 "I/O: read %d chars, buffer %d/%d\n",
3326 nbchars, in->buffer->use, in->buffer->size);
3332 * xmlParserInputBufferRead:
3333 * @in: a buffered parser input
3334 * @len: indicative value of the amount of chars to read
3336 * Refresh the content of the input buffer, the old data are considered
3338 * This routine handle the I18N transcoding to internal UTF-8
3340 * Returns the number of chars read and stored in the buffer, or -1
3344 xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
3345 if ((in == NULL) || (in->error)) return(-1);
3346 if (in->readcallback != NULL)
3347 return(xmlParserInputBufferGrow(in, len));
3348 else if ((in->buffer != NULL) &&
3349 (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE))
3355 #ifdef LIBXML_OUTPUT_ENABLED
3357 * xmlOutputBufferWrite:
3358 * @out: a buffered parser output
3359 * @len: the size in bytes of the array.
3360 * @buf: an char array
3362 * Write the content of the array in the output I/O buffer
3363 * This routine handle the I18N transcoding from internal UTF-8
3364 * The buffer is lossless, i.e. will store in case of partial
3365 * or delayed writes.
3367 * Returns the number of chars immediately written, or -1
3371 xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
3372 int nbchars = 0; /* number of chars to output to I/O */
3373 int ret; /* return from function call */
3374 int written = 0; /* number of char written to I/O so far */
3375 int chunk; /* number of byte curreent processed from buf */
3377 if ((out == NULL) || (out->error)) return(-1);
3378 if (len < 0) return(0);
3379 if (out->error) return(-1);
3383 if (chunk > 4 * MINLEN)
3387 * first handle encoding stuff.
3389 if (out->encoder != NULL) {
3391 * Store the data in the incoming raw buffer
3393 if (out->conv == NULL) {
3394 out->conv = xmlBufferCreate();
3396 ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
3400 if ((out->buffer->use < MINLEN) && (chunk == len))
3404 * convert as much as possible to the parser reading buffer.
3406 ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
3407 if ((ret < 0) && (ret != -3)) {
3408 xmlIOErr(XML_IO_ENCODER, NULL);
3409 out->error = XML_IO_ENCODER;
3412 nbchars = out->conv->use;
3414 ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
3417 nbchars = out->buffer->use;
3422 if ((nbchars < MINLEN) && (len <= 0))
3425 if (out->writecallback) {
3427 * second write the stuff to the I/O channel
3429 if (out->encoder != NULL) {
3430 ret = out->writecallback(out->context,
3431 (const char *)out->conv->content, nbchars);
3433 xmlBufferShrink(out->conv, ret);
3435 ret = out->writecallback(out->context,
3436 (const char *)out->buffer->content, nbchars);
3438 xmlBufferShrink(out->buffer, ret);
3441 xmlIOErr(XML_IO_WRITE, NULL);
3442 out->error = XML_IO_WRITE;
3445 out->written += ret;
3452 xmlGenericError(xmlGenericErrorContext,
3453 "I/O: wrote %d chars\n", written);
3460 * @out: a pointer to an array of bytes to store the result
3461 * @outlen: the length of @out
3462 * @in: a pointer to an array of unescaped UTF-8 bytes
3463 * @inlen: the length of @in
3465 * Take a block of UTF-8 chars in and escape them.
3466 * Returns 0 if success, or -1 otherwise
3467 * The value of @inlen after return is the number of octets consumed
3468 * if the return value is positive, else unpredictable.
3469 * The value of @outlen after return is the number of octets consumed.
3472 xmlEscapeContent(unsigned char* out, int *outlen,
3473 const xmlChar* in, int *inlen) {
3474 unsigned char* outstart = out;
3475 const unsigned char* base = in;
3476 unsigned char* outend = out + *outlen;
3477 const unsigned char* inend;
3479 inend = in + (*inlen);
3481 while ((in < inend) && (out < outend)) {
3483 if (outend - out < 4) break;
3488 } else if (*in == '>') {
3489 if (outend - out < 4) break;
3494 } else if (*in == '&') {
3495 if (outend - out < 5) break;
3501 } else if (*in == '\r') {
3502 if (outend - out < 5) break;
3509 *out++ = (unsigned char) *in;
3513 *outlen = out - outstart;
3519 * xmlOutputBufferWriteEscape:
3520 * @out: a buffered parser output
3521 * @str: a zero terminated UTF-8 string
3522 * @escaping: an optional escaping function (or NULL)
3524 * Write the content of the string in the output I/O buffer
3525 * This routine escapes the caracters and then handle the I18N
3526 * transcoding from internal UTF-8
3527 * The buffer is lossless, i.e. will store in case of partial
3528 * or delayed writes.
3530 * Returns the number of chars immediately written, or -1
3534 xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
3535 xmlCharEncodingOutputFunc escaping) {
3536 int nbchars = 0; /* number of chars to output to I/O */
3537 int ret; /* return from function call */
3538 int written = 0; /* number of char written to I/O so far */
3539 int oldwritten=0;/* loop guard */
3540 int chunk; /* number of byte currently processed from str */
3541 int len; /* number of bytes in str */
3542 int cons; /* byte from str consumed */
3544 if ((out == NULL) || (out->error) || (str == NULL) ||
3545 (out->buffer == NULL) ||
3546 (out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1);
3547 len = strlen((const char *)str);
3548 if (len < 0) return(0);
3549 if (out->error) return(-1);
3550 if (escaping == NULL) escaping = xmlEscapeContent;
3553 oldwritten = written;
3556 * how many bytes to consume and how many bytes to store.
3559 chunk = (out->buffer->size - out->buffer->use) - 1;
3562 * make sure we have enough room to save first, if this is
3563 * not the case force a flush, but make sure we stay in the loop
3566 if (xmlBufferGrow(out->buffer, out->buffer->size + 100) < 0)
3573 * first handle encoding stuff.
3575 if (out->encoder != NULL) {
3577 * Store the data in the incoming raw buffer
3579 if (out->conv == NULL) {
3580 out->conv = xmlBufferCreate();
3582 ret = escaping(out->buffer->content + out->buffer->use ,
3583 &chunk, str, &cons);
3584 if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
3586 out->buffer->use += chunk;
3587 out->buffer->content[out->buffer->use] = 0;
3589 if ((out->buffer->use < MINLEN) && (cons == len))
3593 * convert as much as possible to the output buffer.
3595 ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
3596 if ((ret < 0) && (ret != -3)) {
3597 xmlIOErr(XML_IO_ENCODER, NULL);
3598 out->error = XML_IO_ENCODER;
3601 nbchars = out->conv->use;
3603 ret = escaping(out->buffer->content + out->buffer->use ,
3604 &chunk, str, &cons);
3605 if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
3607 out->buffer->use += chunk;
3608 out->buffer->content[out->buffer->use] = 0;
3609 nbchars = out->buffer->use;
3614 if ((nbchars < MINLEN) && (len <= 0))
3617 if (out->writecallback) {
3619 * second write the stuff to the I/O channel
3621 if (out->encoder != NULL) {
3622 ret = out->writecallback(out->context,
3623 (const char *)out->conv->content, nbchars);
3625 xmlBufferShrink(out->conv, ret);
3627 ret = out->writecallback(out->context,
3628 (const char *)out->buffer->content, nbchars);
3630 xmlBufferShrink(out->buffer, ret);
3633 xmlIOErr(XML_IO_WRITE, NULL);
3634 out->error = XML_IO_WRITE;
3637 out->written += ret;
3638 } else if (out->buffer->size - out->buffer->use < MINLEN) {
3639 xmlBufferResize(out->buffer, out->buffer->size + MINLEN);
3642 } while ((len > 0) && (oldwritten != written));
3646 xmlGenericError(xmlGenericErrorContext,
3647 "I/O: wrote %d chars\n", written);
3653 * xmlOutputBufferWriteString:
3654 * @out: a buffered parser output
3655 * @str: a zero terminated C string
3657 * Write the content of the string in the output I/O buffer
3658 * This routine handle the I18N transcoding from internal UTF-8
3659 * The buffer is lossless, i.e. will store in case of partial
3660 * or delayed writes.
3662 * Returns the number of chars immediately written, or -1
3666 xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
3669 if ((out == NULL) || (out->error)) return(-1);
3675 return(xmlOutputBufferWrite(out, len, str));
3680 * xmlOutputBufferFlush:
3681 * @out: a buffered output
3683 * flushes the output I/O channel
3685 * Returns the number of byte written or -1 in case of error.
3688 xmlOutputBufferFlush(xmlOutputBufferPtr out) {
3689 int nbchars = 0, ret = 0;
3691 if ((out == NULL) || (out->error)) return(-1);
3693 * first handle encoding stuff.
3695 if ((out->conv != NULL) && (out->encoder != NULL)) {
3697 * convert as much as possible to the parser reading buffer.
3699 nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
3701 xmlIOErr(XML_IO_ENCODER, NULL);
3702 out->error = XML_IO_ENCODER;
3708 * second flush the stuff to the I/O channel
3710 if ((out->conv != NULL) && (out->encoder != NULL) &&
3711 (out->writecallback != NULL)) {
3712 ret = out->writecallback(out->context,
3713 (const char *)out->conv->content, out->conv->use);
3715 xmlBufferShrink(out->conv, ret);
3716 } else if (out->writecallback != NULL) {
3717 ret = out->writecallback(out->context,
3718 (const char *)out->buffer->content, out->buffer->use);
3720 xmlBufferShrink(out->buffer, ret);
3723 xmlIOErr(XML_IO_FLUSH, NULL);
3724 out->error = XML_IO_FLUSH;
3727 out->written += ret;
3730 xmlGenericError(xmlGenericErrorContext,
3731 "I/O: flushed %d chars\n", ret);
3735 #endif /* LIBXML_OUTPUT_ENABLED */
3738 * xmlParserGetDirectory:
3739 * @filename: the path to a file
3741 * lookup the directory for that file
3743 * Returns a new allocated string containing the directory, or NULL.
3746 xmlParserGetDirectory(const char *filename) {
3751 #ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */
3755 if (xmlInputCallbackInitialized == 0)
3756 xmlRegisterDefaultInputCallbacks();
3758 if (filename == NULL) return(NULL);
3760 #if defined(WIN32) && !defined(__CYGWIN__)
3761 # define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
3763 # define IS_XMLPGD_SEP(ch) (ch=='/')
3766 strncpy(dir, filename, 1023);
3768 cur = &dir[strlen(dir)];
3770 if (IS_XMLPGD_SEP(*cur)) break;
3773 if (IS_XMLPGD_SEP(*cur)) {
3774 if (cur == dir) dir[1] = 0;
3776 ret = xmlMemStrdup(dir);
3778 if (getcwd(dir, 1024) != NULL) {
3780 ret = xmlMemStrdup(dir);
3784 #undef IS_XMLPGD_SEP
3787 /****************************************************************
3789 * External entities loading *
3791 ****************************************************************/
3794 * xmlCheckHTTPInput:
3795 * @ctxt: an XML parser context
3796 * @ret: an XML parser input
3798 * Check an input in case it was created from an HTTP stream, in that
3799 * case it will handle encoding and update of the base URL in case of
3800 * redirection. It also checks for HTTP errors in which case the input
3801 * is cleanly freed up and an appropriate error is raised in context
3803 * Returns the input or NULL in case of HTTP error.
3806 xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
3807 #ifdef LIBXML_HTTP_ENABLED
3808 if ((ret != NULL) && (ret->buf != NULL) &&
3809 (ret->buf->readcallback == xmlIOHTTPRead) &&
3810 (ret->buf->context != NULL)) {
3811 const char *encoding;
3816 code = xmlNanoHTTPReturnCode(ret->buf->context);
3819 if (ret->filename != NULL)
3820 __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
3821 (const char *) ret->filename);
3823 __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
3824 xmlFreeInputStream(ret);
3828 mime = xmlNanoHTTPMimeType(ret->buf->context);
3829 if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
3830 (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
3831 encoding = xmlNanoHTTPEncoding(ret->buf->context);
3832 if (encoding != NULL) {
3833 xmlCharEncodingHandlerPtr handler;
3835 handler = xmlFindCharEncodingHandler(encoding);
3836 if (handler != NULL) {
3837 xmlSwitchInputEncoding(ctxt, ret, handler);
3839 __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
3840 "Unknown encoding %s",
3841 BAD_CAST encoding, NULL);
3843 if (ret->encoding == NULL)
3844 ret->encoding = xmlStrdup(BAD_CAST encoding);
3847 } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
3850 redir = xmlNanoHTTPRedir(ret->buf->context);
3851 if (redir != NULL) {
3852 if (ret->filename != NULL)
3853 xmlFree((xmlChar *) ret->filename);
3854 if (ret->directory != NULL) {
3855 xmlFree((xmlChar *) ret->directory);
3856 ret->directory = NULL;
3859 (char *) xmlStrdup((const xmlChar *) redir);
3867 static int xmlNoNetExists(const char *URL) {
3873 if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
3874 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3879 else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
3880 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
3888 return xmlCheckFilename(path);
3891 #ifdef LIBXML_CATALOG_ENABLED
3894 * xmlResolveResourceFromCatalog:
3895 * @URL: the URL for the entity to load
3896 * @ID: the System ID for the entity to load
3897 * @ctxt: the context in which the entity is called or NULL
3899 * Resolves the URL and ID against the appropriate catalog.
3900 * This function is used by xmlDefaultExternalEntityLoader and
3901 * xmlNoNetExternalEntityLoader.
3903 * Returns a new allocated URL, or NULL.
3906 xmlResolveResourceFromCatalog(const char *URL, const char *ID,
3907 xmlParserCtxtPtr ctxt) {
3908 xmlChar *resource = NULL;
3909 xmlCatalogAllow pref;
3912 * If the resource doesn't exists as a file,
3913 * try to load it from the resource pointed in the catalogs
3915 pref = xmlCatalogGetDefaults();
3917 if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
3921 if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3922 ((pref == XML_CATA_ALLOW_ALL) ||
3923 (pref == XML_CATA_ALLOW_DOCUMENT))) {
3924 resource = xmlCatalogLocalResolve(ctxt->catalogs,
3925 (const xmlChar *)ID,
3926 (const xmlChar *)URL);
3929 * Try a global lookup
3931 if ((resource == NULL) &&
3932 ((pref == XML_CATA_ALLOW_ALL) ||
3933 (pref == XML_CATA_ALLOW_GLOBAL))) {
3934 resource = xmlCatalogResolve((const xmlChar *)ID,
3935 (const xmlChar *)URL);
3937 if ((resource == NULL) && (URL != NULL))
3938 resource = xmlStrdup((const xmlChar *) URL);
3941 * TODO: do an URI lookup on the reference
3943 if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
3944 xmlChar *tmp = NULL;
3946 if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
3947 ((pref == XML_CATA_ALLOW_ALL) ||
3948 (pref == XML_CATA_ALLOW_DOCUMENT))) {
3949 tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
3951 if ((tmp == NULL) &&
3952 ((pref == XML_CATA_ALLOW_ALL) ||
3953 (pref == XML_CATA_ALLOW_GLOBAL))) {
3954 tmp = xmlCatalogResolveURI(resource);
3970 * xmlDefaultExternalEntityLoader:
3971 * @URL: the URL for the entity to load
3972 * @ID: the System ID for the entity to load
3973 * @ctxt: the context in which the entity is called or NULL
3975 * By default we don't load external entitites, yet.
3977 * Returns a new allocated xmlParserInputPtr, or NULL.
3979 static xmlParserInputPtr
3980 xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
3981 xmlParserCtxtPtr ctxt)
3983 xmlParserInputPtr ret = NULL;
3984 xmlChar *resource = NULL;
3986 #ifdef DEBUG_EXTERNAL_ENTITIES
3987 xmlGenericError(xmlGenericErrorContext,
3988 "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
3990 if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
3991 int options = ctxt->options;
3993 ctxt->options -= XML_PARSE_NONET;
3994 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
3995 ctxt->options = options;
3998 #ifdef LIBXML_CATALOG_ENABLED
3999 resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
4002 if (resource == NULL)
4003 resource = (xmlChar *) URL;
4005 if (resource == NULL) {
4008 __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
4011 ret = xmlNewInputFromFile(ctxt, (const char *) resource);
4012 if ((resource != NULL) && (resource != (xmlChar *) URL))
4017 static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
4018 xmlDefaultExternalEntityLoader;
4021 * xmlSetExternalEntityLoader:
4022 * @f: the new entity resolver function
4024 * Changes the defaultexternal entity resolver function for the application
4027 xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
4028 xmlCurrentExternalEntityLoader = f;
4032 * xmlGetExternalEntityLoader:
4034 * Get the default external entity resolver function for the application
4036 * Returns the xmlExternalEntityLoader function pointer
4038 xmlExternalEntityLoader
4039 xmlGetExternalEntityLoader(void) {
4040 return(xmlCurrentExternalEntityLoader);
4044 * xmlLoadExternalEntity:
4045 * @URL: the URL for the entity to load
4046 * @ID: the Public ID for the entity to load
4047 * @ctxt: the context in which the entity is called or NULL
4049 * Load an external entity, note that the use of this function for
4050 * unparsed entities may generate problems
4052 * Returns the xmlParserInputPtr or NULL
4055 xmlLoadExternalEntity(const char *URL, const char *ID,
4056 xmlParserCtxtPtr ctxt) {
4057 if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
4058 char *canonicFilename;
4059 xmlParserInputPtr ret;
4061 canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
4062 if (canonicFilename == NULL) {
4063 xmlIOErrMemory("building canonical path\n");
4067 ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
4068 xmlFree(canonicFilename);
4071 return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
4074 /************************************************************************
4076 * Disabling Network access *
4078 ************************************************************************/
4081 * xmlNoNetExternalEntityLoader:
4082 * @URL: the URL for the entity to load
4083 * @ID: the System ID for the entity to load
4084 * @ctxt: the context in which the entity is called or NULL
4086 * A specific entity loader disabling network accesses, though still
4087 * allowing local catalog accesses for resolution.
4089 * Returns a new allocated xmlParserInputPtr, or NULL.
4092 xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
4093 xmlParserCtxtPtr ctxt) {
4094 xmlParserInputPtr input = NULL;
4095 xmlChar *resource = NULL;
4097 #ifdef LIBXML_CATALOG_ENABLED
4098 resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
4101 if (resource == NULL)
4102 resource = (xmlChar *) URL;
4104 if (resource != NULL) {
4105 if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
4106 (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
4107 xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
4108 if (resource != (xmlChar *) URL)
4113 input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
4114 if (resource != (xmlChar *) URL)
4119 #define bottom_xmlIO
4120 #include "elfgcchack.h"