Revert directory structure changes
diff --git a/xmlIO.c b/xmlIO.c
new file mode 100644
index 0000000..290ceab
--- /dev/null
+++ b/xmlIO.c
@@ -0,0 +1,1743 @@
+/*
+ * xmlIO.c : implementation of the I/O interfaces used by the parser
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@w3.org
+ *
+ * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
+ */
+
+#ifdef WIN32
+#include "win32config.h"
+#else
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+/* Figure a portable way to know if a file is a directory. */
+#ifndef HAVE_STAT
+#  ifdef HAVE__STAT
+#    define stat(x,y) _stat(x,y)
+#    define HAVE_STAT
+#  endif
+#endif
+#ifdef HAVE_STAT
+#  ifndef S_ISDIR
+#    ifdef _S_ISDIR
+#      define S_ISDIR(x) _S_ISDIR(x)
+#    else
+#      ifdef S_IFDIR
+#        ifndef S_IFMT
+#          ifdef _S_IFMT
+#            define S_IFMT _S_IFMT
+#          endif
+#        endif
+#        ifdef S_IFMT
+#          define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlIO.h>
+#include <libxml/nanohttp.h>
+#include <libxml/nanoftp.h>
+#include <libxml/xmlerror.h>
+
+#ifdef VMS
+#define xmlRegisterDefaultInputCallbacks xmlRegisterDefInputCallbacks
+#define xmlRegisterDefaultOutputCallbacks xmlRegisterDefOutputCallbacks
+#endif
+
+/* #define VERBOSE_FAILURE */
+/* #define DEBUG_EXTERNAL_ENTITIES */
+/* #define DEBUG_INPUT */
+
+#ifdef DEBUG_INPUT
+#define MINLEN 40
+#else
+#define MINLEN 4000
+#endif
+
+/*
+ * Input I/O callback sets
+ */
+typedef struct _xmlInputCallback {
+    xmlInputMatchCallback matchcallback;
+    xmlInputOpenCallback opencallback;
+    xmlInputReadCallback readcallback;
+    xmlInputCloseCallback closecallback;
+} xmlInputCallback;
+
+#define MAX_INPUT_CALLBACK 15
+
+xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
+int xmlInputCallbackNr = 0;
+int xmlInputCallbackInitialized = 0;
+
+/*
+ * Output I/O callback sets
+ */
+typedef struct _xmlOutputCallback {
+    xmlOutputMatchCallback matchcallback;
+    xmlOutputOpenCallback opencallback;
+    xmlOutputWriteCallback writecallback;
+    xmlOutputCloseCallback closecallback;
+} xmlOutputCallback;
+
+#define MAX_OUTPUT_CALLBACK 15
+
+xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
+int xmlOutputCallbackNr = 0;
+int xmlOutputCallbackInitialized = 0;
+
+/************************************************************************
+ *									*
+ *		Standard I/O for file accesses				*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlCheckFilename
+ * @path:  the path to check
+ *
+ * function checks to see if @path is a valid source
+ * (file, socket...) for XML.
+ *
+ * if stat is not available on the target machine,
+ * returns 1.  if stat fails, returns 0 (if calling
+ * stat on the filename fails, it can't be right).
+ * if stat succeeds and the file is a directory,
+ * sets errno to EISDIR and returns 0.  otherwise
+ * returns 1.
+ */
+
+static int
+xmlCheckFilename (const char *path)
+{
+#ifdef HAVE_STAT
+#ifdef S_ISDIR
+    struct stat stat_buffer;
+
+    if (stat(path, &stat_buffer) == -1)
+        return 0;
+
+    if (S_ISDIR(stat_buffer.st_mode)) {
+        errno = EISDIR;
+        return 0;
+    }
+
+#endif
+#endif
+    return 1;
+}
+
+int
+xmlNop(void) {
+    return(0);
+}
+
+/**
+ * xmlFdMatch:
+ * @filename:  the URI for matching
+ *
+ * input from file descriptor
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+int
+xmlFdMatch (const char *filename) {
+    return(1);
+}
+
+/**
+ * xmlFdOpen:
+ * @filename:  the URI for matching
+ *
+ * input from file descriptor, supports compressed input
+ * if @filename is " " then the standard input is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlFdOpen (const char *filename) {
+    const char *path = NULL;
+    int fd;
+
+    if (!strcmp(filename, "-")) {
+	fd = 0;
+	return((void *) fd);
+    }
+
+    if (!strncmp(filename, "file://localhost", 16))
+	path = &filename[16];
+    else if (!strncmp(filename, "file:///", 8))
+	path = &filename[8];
+    else if (filename[0] == '/')
+	path = filename;
+    if (path == NULL)
+	return(NULL);
+
+#ifdef WIN32
+    fd = _open (path, O_RDONLY | _O_BINARY);
+#else
+    fd = open (path, O_RDONLY);
+#endif
+
+    return((void *) fd);
+}
+
+/**
+ * xmlFdOpenW:
+ * @filename:  the URI for matching
+ *
+ * input from file descriptor,
+ * if @filename is "-" then the standard output is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlFdOpenW (const char *filename) {
+    const char *path = NULL;
+    int fd;
+
+    if (!strcmp(filename, "-")) {
+	fd = 1;
+	return((void *) fd);
+    }
+
+    if (!strncmp(filename, "file://localhost", 16))
+	path = &filename[16];
+    else if (!strncmp(filename, "file:///", 8))
+	path = &filename[8];
+    else if (filename[0] == '/')
+	path = filename;
+    if (path == NULL)
+	return(NULL);
+
+    fd = open (path, O_WRONLY);
+
+    return((void *) fd);
+}
+
+/**
+ * xmlFdRead:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to read
+ *
+ * Read @len bytes to @buffer from the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlFdRead (void * context, char * buffer, int len) {
+    return(read((int) context, &buffer[0], len));
+}
+
+/**
+ * xmlFdWrite:
+ * @context:  the I/O context
+ * @buffer:  where to get data
+ * @len:  number of bytes to write
+ *
+ * Write @len bytes from @buffer to the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlFdWrite (void * context, const char * buffer, int len) {
+    return(write((int) context, &buffer[0], len));
+}
+
+/**
+ * xmlFdClose:
+ * @context:  the I/O context
+ *
+ * Close an I/O channel
+ */
+void
+xmlFdClose (void * context) {
+    close((int) context);
+}
+
+/**
+ * xmlFileMatch:
+ * @filename:  the URI for matching
+ *
+ * input from FILE *
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+int
+xmlFileMatch (const char *filename) {
+    return(1);
+}
+
+/**
+ * xmlFileOpen:
+ * @filename:  the URI for matching
+ *
+ * input from FILE *, supports compressed input
+ * if @filename is " " then the standard input is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlFileOpen (const char *filename) {
+    const char *path = NULL;
+    FILE *fd;
+
+    if (!strcmp(filename, "-")) {
+	fd = stdin;
+	return((void *) fd);
+    }
+
+    if (!strncmp(filename, "file://localhost", 16))
+	path = &filename[16];
+    else if (!strncmp(filename, "file:///", 8))
+	path = &filename[8];
+    else 
+	path = filename;
+
+    if (path == NULL)
+	return(NULL);
+    if (!xmlCheckFilename(path))
+        return(NULL);
+
+#ifdef WIN32
+    fd = fopen(path, "rb");
+#else
+    fd = fopen(path, "r");
+#endif /* WIN32 */
+    return((void *) fd);
+}
+
+/**
+ * xmlFileOpenW:
+ * @filename:  the URI for matching
+ *
+ * output to from FILE *,
+ * if @filename is "-" then the standard output is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlFileOpenW (const char *filename) {
+    const char *path = NULL;
+    FILE *fd;
+
+    if (!strcmp(filename, "-")) {
+	fd = stdout;
+	return((void *) fd);
+    }
+
+    if (!strncmp(filename, "file://localhost", 16))
+	path = &filename[16];
+    else if (!strncmp(filename, "file:///", 8))
+	path = &filename[8];
+    else 
+	path = filename;
+
+    if (path == NULL)
+	return(NULL);
+
+    fd = fopen(path, "w");
+    return((void *) fd);
+}
+
+/**
+ * xmlFileRead:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
+ *
+ * Read @len bytes to @buffer from the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlFileRead (void * context, char * buffer, int len) {
+    return(fread(&buffer[0], 1,  len, (FILE *) context));
+}
+
+/**
+ * xmlFileWrite:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
+ *
+ * Write @len bytes from @buffer to the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlFileWrite (void * context, const char * buffer, int len) {
+    return(fwrite(&buffer[0], 1,  len, (FILE *) context));
+}
+
+/**
+ * xmlFileClose:
+ * @context:  the I/O context
+ *
+ * Close an I/O channel
+ */
+void
+xmlFileClose (void * context) {
+    fclose((FILE *) context);
+}
+
+/**
+ * xmlFileFlush:
+ * @context:  the I/O context
+ *
+ * Flush an I/O channel
+ */
+void
+xmlFileFlush (void * context) {
+    fflush((FILE *) context);
+}
+
+#ifdef HAVE_ZLIB_H
+/************************************************************************
+ *									*
+ *		I/O for compressed file accesses			*
+ *									*
+ ************************************************************************/
+/**
+ * xmlGzfileMatch:
+ * @filename:  the URI for matching
+ *
+ * input from compressed file test
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+int
+xmlGzfileMatch (const char *filename) {
+    return(1);
+}
+
+/**
+ * xmlGzfileOpen:
+ * @filename:  the URI for matching
+ *
+ * input from compressed file open
+ * if @filename is " " then the standard input is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlGzfileOpen (const char *filename) {
+    const char *path = NULL;
+    gzFile fd;
+
+    if (!strcmp(filename, "-")) {
+        fd = gzdopen(fileno(stdin), "rb");
+	return((void *) fd);
+    }
+
+    if (!strncmp(filename, "file://localhost", 16))
+	path = &filename[16];
+    else if (!strncmp(filename, "file:///", 8))
+	path = &filename[7];
+    else 
+	path = filename;
+
+    if (path == NULL)
+	return(NULL);
+    if (!xmlCheckFilename(path))
+        return(NULL);
+
+    fd = gzopen(path, "rb");
+    return((void *) fd);
+}
+
+/**
+ * xmlGzfileOpenW:
+ * @filename:  the URI for matching
+ * @compression:  the compression factor (0 - 9 included)
+ *
+ * input from compressed file open
+ * if @filename is " " then the standard input is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlGzfileOpenW (const char *filename, int compression) {
+    const char *path = NULL;
+    char mode[15];
+    gzFile fd;
+
+    sprintf(mode, "wb%d", compression);
+    if (!strcmp(filename, "-")) {
+        fd = gzdopen(1, mode);
+	return((void *) fd);
+    }
+
+    if (!strncmp(filename, "file://localhost", 16))
+	path = &filename[16];
+    else if (!strncmp(filename, "file:///", 8))
+	path = &filename[8];
+    else 
+	path = filename;
+
+    if (path == NULL)
+	return(NULL);
+
+    fd = gzopen(path, mode);
+    return((void *) fd);
+}
+
+/**
+ * xmlGzfileRead:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
+ *
+ * Read @len bytes to @buffer from the compressed I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlGzfileRead (void * context, char * buffer, int len) {
+    return(gzread((gzFile) context, &buffer[0], len));
+}
+
+/**
+ * xmlGzfileWrite:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
+ *
+ * Write @len bytes from @buffer to the compressed I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlGzfileWrite (void * context, const char * buffer, int len) {
+    return(gzwrite((gzFile) context, (char *) &buffer[0], len));
+}
+
+/**
+ * xmlGzfileClose:
+ * @context:  the I/O context
+ *
+ * Close a compressed I/O channel
+ */
+void
+xmlGzfileClose (void * context) {
+    gzclose((gzFile) context);
+}
+#endif /* HAVE_ZLIB_H */
+
+#ifdef LIBXML_HTTP_ENABLED
+/************************************************************************
+ *									*
+ *			I/O for HTTP file accesses			*
+ *									*
+ ************************************************************************/
+/**
+ * xmlIOHTTPMatch:
+ * @filename:  the URI for matching
+ *
+ * check if the URI matches an HTTP one
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+int
+xmlIOHTTPMatch (const char *filename) {
+    if (!strncmp(filename, "http://", 7))
+	return(1);
+    return(0);
+}
+
+/**
+ * xmlIOHTTPOpen:
+ * @filename:  the URI for matching
+ *
+ * open an HTTP I/O channel
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlIOHTTPOpen (const char *filename) {
+    return(xmlNanoHTTPOpen(filename, NULL));
+}
+
+/**
+ * xmlIOHTTPRead:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
+ *
+ * Read @len bytes to @buffer from the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int 
+xmlIOHTTPRead(void * context, char * buffer, int len) {
+    return(xmlNanoHTTPRead(context, &buffer[0], len));
+}
+
+/**
+ * xmlIOHTTPClose:
+ * @context:  the I/O context
+ *
+ * Close an HTTP I/O channel
+ */
+void
+xmlIOHTTPClose (void * context) {
+    xmlNanoHTTPClose(context);
+}
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+/************************************************************************
+ *									*
+ *			I/O for FTP file accesses			*
+ *									*
+ ************************************************************************/
+/**
+ * xmlIOFTPMatch:
+ * @filename:  the URI for matching
+ *
+ * check if the URI matches an FTP one
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+int
+xmlIOFTPMatch (const char *filename) {
+    if (!strncmp(filename, "ftp://", 6))
+	return(1);
+    return(0);
+}
+
+/**
+ * xmlIOFTPOpen:
+ * @filename:  the URI for matching
+ *
+ * open an FTP I/O channel
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlIOFTPOpen (const char *filename) {
+    return(xmlNanoFTPOpen(filename));
+}
+
+/**
+ * xmlIOFTPRead:
+ * @context:  the I/O context
+ * @buffer:  where to drop data
+ * @len:  number of bytes to write
+ *
+ * Read @len bytes to @buffer from the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int 
+xmlIOFTPRead(void * context, char * buffer, int len) {
+    return(xmlNanoFTPRead(context, &buffer[0], len));
+}
+
+/**
+ * xmlIOFTPClose:
+ * @context:  the I/O context
+ *
+ * Close an FTP I/O channel
+ */
+void
+xmlIOFTPClose (void * context) {
+    xmlNanoFTPClose(context);
+}
+#endif /* LIBXML_FTP_ENABLED */
+
+
+/**
+ * xmlRegisterInputCallbacks:
+ * @match:  the xmlInputMatchCallback
+ * @open:  the xmlInputOpenCallback
+ * @read:  the xmlInputReadCallback
+ * @close:  the xmlInputCloseCallback
+ *
+ * Register a new set of I/O callback for handling parser input.
+ *
+ * Returns the registered handler number or -1 in case of error
+ */
+int
+xmlRegisterInputCallbacks(xmlInputMatchCallback match,
+	xmlInputOpenCallback open, xmlInputReadCallback read,
+	xmlInputCloseCallback close) {
+    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
+	return(-1);
+    }
+    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = match;
+    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = open;
+    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = read;
+    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = close;
+    return(xmlInputCallbackNr++);
+}
+
+/**
+ * xmlRegisterOutputCallbacks:
+ * @match:  the xmlOutputMatchCallback
+ * @open:  the xmlOutputOpenCallback
+ * @write:  the xmlOutputWriteCallback
+ * @close:  the xmlOutputCloseCallback
+ *
+ * Register a new set of I/O callback for handling output.
+ *
+ * Returns the registered handler number or -1 in case of error
+ */
+int
+xmlRegisterOutputCallbacks(xmlOutputMatchCallback match,
+	xmlOutputOpenCallback open, xmlOutputWriteCallback write,
+	xmlOutputCloseCallback close) {
+    if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
+	return(-1);
+    }
+    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = match;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = open;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = write;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = close;
+    return(xmlOutputCallbackNr++);
+}
+
+/**
+ * xmlRegisterDefaultInputCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ */
+void
+#ifdef VMS
+xmlRegisterDefInputCallbacks
+#else
+xmlRegisterDefaultInputCallbacks
+#endif
+(void) {
+    if (xmlInputCallbackInitialized)
+	return;
+
+    xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
+	                      xmlFileRead, xmlFileClose);
+#ifdef HAVE_ZLIB_H
+    xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
+	                      xmlGzfileRead, xmlGzfileClose);
+#endif /* HAVE_ZLIB_H */
+
+#ifdef LIBXML_HTTP_ENABLED
+    xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
+	                      xmlIOHTTPRead, xmlIOHTTPClose);
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+    xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
+	                      xmlIOFTPRead, xmlIOFTPClose);
+#endif /* LIBXML_FTP_ENABLED */
+    xmlInputCallbackInitialized = 1;
+}
+
+/**
+ * xmlRegisterDefaultOutputCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ */
+void
+#ifdef VMS
+xmlRegisterDefOutputCallbacks
+#else
+xmlRegisterDefaultOutputCallbacks
+#endif
+(void) {
+    if (xmlOutputCallbackInitialized)
+	return;
+
+    xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
+	                      xmlFileWrite, xmlFileClose);
+/*********************************
+ No way a-priori to distinguish between gzipped files from
+ uncompressed ones except opening if existing then closing
+ and saving with same compression ratio ... a pain.
+
+#ifdef HAVE_ZLIB_H
+    xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
+	                       xmlGzfileWrite, xmlGzfileClose);
+#endif
+ No HTTP PUT support yet, patches welcome
+
+#ifdef LIBXML_HTTP_ENABLED
+    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
+	                       xmlIOHTTPWrite, xmlIOHTTPClose);
+#endif
+
+ Nor FTP PUT ....
+#ifdef LIBXML_FTP_ENABLED
+    xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
+	                       xmlIOFTPWrite, xmlIOFTPClose);
+#endif
+ **********************************/
+    xmlOutputCallbackInitialized = 1;
+}
+
+/**
+ * xmlAllocParserInputBuffer:
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered parser input for progressive parsing
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+xmlAllocParserInputBuffer(xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
+
+    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
+    if (ret == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlAllocParserInputBuffer : out of memory!\n");
+	return(NULL);
+    }
+    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
+    ret->buffer = xmlBufferCreate();
+    if (ret->buffer == NULL) {
+        xmlFree(ret);
+	return(NULL);
+    }
+    ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
+    ret->encoder = xmlGetCharEncodingHandler(enc);
+    if (ret->encoder != NULL)
+        ret->raw = xmlBufferCreate();
+    else
+        ret->raw = NULL;
+    ret->readcallback = NULL;
+    ret->closecallback = NULL;
+    ret->context = NULL;
+
+    return(ret);
+}
+
+/**
+ * xmlAllocOutputBuffer:
+ * @encoder:  the encoding converter or NULL
+ *
+ * Create a buffered parser output
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
+    xmlOutputBufferPtr ret;
+
+    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
+    if (ret == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlAllocOutputBuffer : out of memory!\n");
+	return(NULL);
+    }
+    memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
+    ret->buffer = xmlBufferCreate();
+    if (ret->buffer == NULL) {
+        xmlFree(ret);
+	return(NULL);
+    }
+    ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
+    ret->encoder = encoder;
+    if (encoder != NULL) {
+        ret->conv = xmlBufferCreateSize(4000);
+	/*
+	 * This call is designed to initiate the encoder state
+	 */
+	xmlCharEncOutFunc(encoder, ret->conv, NULL); 
+    } else
+        ret->conv = NULL;
+    ret->writecallback = NULL;
+    ret->closecallback = NULL;
+    ret->context = NULL;
+    ret->written = 0;
+
+    return(ret);
+}
+
+/**
+ * xmlFreeParserInputBuffer:
+ * @in:  a buffered parser input
+ *
+ * Free up the memory used by a buffered parser input
+ */
+void
+xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
+    if (in->raw) {
+        xmlBufferFree(in->raw);
+	in->raw = NULL;
+    }
+    if (in->encoder != NULL) {
+        xmlCharEncCloseFunc(in->encoder);
+    }
+    if (in->closecallback != NULL) {
+	in->closecallback(in->context);
+    }
+    if (in->buffer != NULL) {
+        xmlBufferFree(in->buffer);
+	in->buffer = NULL;
+    }
+
+    memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
+    xmlFree(in);
+}
+
+/**
+ * xmlOutputBufferClose:
+ * @out:  a buffered output
+ *
+ * flushes and close the output I/O channel
+ * and free up all the associated resources
+ *
+ * Returns the number of byte written or -1 in case of error.
+ */
+int
+xmlOutputBufferClose(xmlOutputBufferPtr out) {
+    int written;
+
+    if (out == NULL)
+        return(-1);
+    if (out->writecallback != NULL)
+	xmlOutputBufferFlush(out);
+    if (out->closecallback != NULL) {
+	out->closecallback(out->context);
+    }
+    written = out->written;
+    if (out->conv) {
+        xmlBufferFree(out->conv);
+	out->conv = NULL;
+    }
+    if (out->encoder != NULL) {
+        xmlCharEncCloseFunc(out->encoder);
+    }
+    if (out->buffer != NULL) {
+        xmlBufferFree(out->buffer);
+	out->buffer = NULL;
+    }
+
+    memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer));
+    xmlFree(out);
+    return(written);
+}
+
+/**
+ * xmlParserInputBufferCreateFilename:
+ * @URI:  a C string containing the URI or filename
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered parser input for the progressive parsing of a file
+ * If filename is "-' then we use stdin as the input.
+ * Automatic support for ZLIB/Compress compressed document is provided
+ * by default if found at compile-time.
+ * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+#ifdef VMS
+xmlParserInputBufferCreateFname
+#else
+xmlParserInputBufferCreateFilename
+#endif
+(const char *URI, xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
+    int i;
+    void *context = NULL;
+
+    if (xmlInputCallbackInitialized == 0)
+	xmlRegisterDefaultInputCallbacks();
+
+    if (URI == NULL) return(NULL);
+
+    /*
+     * Try to find one of the input accept method accepting taht scheme
+     * Go in reverse to give precedence to user defined handlers.
+     */
+    for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
+	if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
+	    (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
+	    context = xmlInputCallbackTable[i].opencallback(URI);
+	    if (context != NULL)
+		break;
+	}
+    }
+    if (context == NULL) {
+	return(NULL);
+    }
+
+    /*
+     * Allocate the Input buffer front-end.
+     */
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret != NULL) {
+	ret->context = context;
+	ret->readcallback = xmlInputCallbackTable[i].readcallback;
+	ret->closecallback = xmlInputCallbackTable[i].closecallback;
+    }
+    return(ret);
+}
+
+/**
+ * xmlOutputBufferCreateFilename:
+ * @URI:  a C string containing the URI or filename
+ * @encoder:  the encoding converter or NULL
+ * @compression:  the compression ration (0 none, 9 max).
+ *
+ * Create a buffered  output for the progressive saving of a file
+ * If filename is "-' then we use stdout as the output.
+ * Automatic support for ZLIB/Compress compressed document is provided
+ * by default if found at compile-time.
+ * TODO: currently if compression is set, the library only support
+ *       writing to a local file.
+ *
+ * Returns the new output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateFilename(const char *URI,
+                              xmlCharEncodingHandlerPtr encoder,
+			      int compression) {
+    xmlOutputBufferPtr ret;
+    int i;
+    void *context = NULL;
+
+    if (xmlOutputCallbackInitialized == 0)
+	xmlRegisterDefaultOutputCallbacks();
+
+    if (URI == NULL) return(NULL);
+
+#ifdef HAVE_ZLIB_H
+    if ((compression > 0) && (compression <= 9)) {
+        context = xmlGzfileOpenW(URI, compression);
+	if (context != NULL) {
+	    ret = xmlAllocOutputBuffer(encoder);
+	    if (ret != NULL) {
+		ret->context = context;
+		ret->writecallback = xmlGzfileWrite;
+		ret->closecallback = xmlGzfileClose;
+	    }
+	    return(ret);
+	}
+    }
+#endif
+
+    /*
+     * Try to find one of the output accept method accepting taht scheme
+     * Go in reverse to give precedence to user defined handlers.
+     */
+    for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
+	if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
+	    (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
+	    context = xmlOutputCallbackTable[i].opencallback(URI);
+	    if (context != NULL)
+		break;
+	}
+    }
+    if (context == NULL) {
+	return(NULL);
+    }
+
+    /*
+     * Allocate the Output buffer front-end.
+     */
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret != NULL) {
+	ret->context = context;
+	ret->writecallback = xmlOutputCallbackTable[i].writecallback;
+	ret->closecallback = xmlOutputCallbackTable[i].closecallback;
+    }
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferCreateFile:
+ * @file:  a FILE* 
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered parser input for the progressive parsing of a FILE *
+ * buffered C I/O
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
+
+    if (xmlInputCallbackInitialized == 0)
+	xmlRegisterDefaultInputCallbacks();
+
+    if (file == NULL) return(NULL);
+
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret != NULL) {
+        ret->context = file;
+	ret->readcallback = xmlFileRead;
+	ret->closecallback = xmlFileFlush;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlOutputBufferCreateFile:
+ * @file:  a FILE* 
+ * @encoder:  the encoding converter or NULL
+ *
+ * Create a buffered output for the progressive saving to a FILE *
+ * buffered C I/O
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
+    xmlOutputBufferPtr ret;
+
+    if (xmlOutputCallbackInitialized == 0)
+	xmlRegisterDefaultOutputCallbacks();
+
+    if (file == NULL) return(NULL);
+
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret != NULL) {
+        ret->context = file;
+	ret->writecallback = xmlFileWrite;
+	ret->closecallback = xmlFileFlush;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferCreateFd:
+ * @fd:  a file descriptor number
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered parser input for the progressive parsing for the input
+ * from a file descriptor
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
+
+    if (fd < 0) return(NULL);
+
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret != NULL) {
+        ret->context = (void *) fd;
+	ret->readcallback = xmlFdRead;
+	ret->closecallback = xmlFdClose;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferCreateMem:
+ * @mem:  the memory input
+ * @size:  the length of the memory block
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered parser input for the progressive parsing for the input
+ * from a memory area.
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
+
+    if (size <= 0) return(NULL);
+    if (mem == NULL) return(NULL);
+
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret != NULL) {
+        ret->context = (void *) mem;
+	ret->readcallback = (xmlInputReadCallback) xmlNop;
+	ret->closecallback = NULL;
+	xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlOutputBufferCreateFd:
+ * @fd:  a file descriptor number
+ * @encoder:  the encoding converter or NULL
+ *
+ * Create a buffered output for the progressive saving 
+ * to a file descriptor
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
+    xmlOutputBufferPtr ret;
+
+    if (fd < 0) return(NULL);
+
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret != NULL) {
+        ret->context = (void *) fd;
+	ret->writecallback = xmlFdWrite;
+	ret->closecallback = xmlFdClose;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferCreateIO:
+ * @ioread:  an I/O read function
+ * @ioclose:  an I/O close function
+ * @ioctx:  an I/O handler
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered parser input for the progressive parsing for the input
+ * from an I/O handler
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
+	 xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
+    xmlParserInputBufferPtr ret;
+
+    if (ioread == NULL) return(NULL);
+
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret != NULL) {
+        ret->context = (void *) ioctx;
+	ret->readcallback = ioread;
+	ret->closecallback = ioclose;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlOutputBufferCreateIO:
+ * @iowrite:  an I/O write function
+ * @ioclose:  an I/O close function
+ * @ioctx:  an I/O handler
+ * @enc:  the charset encoding if known
+ *
+ * Create a buffered output for the progressive saving
+ * to an I/O handler
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
+	 xmlOutputCloseCallback  ioclose, void *ioctx,
+	 xmlCharEncodingHandlerPtr encoder) {
+    xmlOutputBufferPtr ret;
+
+    if (iowrite == NULL) return(NULL);
+
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret != NULL) {
+        ret->context = (void *) ioctx;
+	ret->writecallback = iowrite;
+	ret->closecallback = ioclose;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferPush:
+ * @in:  a buffered parser input
+ * @len:  the size in bytes of the array.
+ * @buf:  an char array
+ *
+ * Push the content of the arry in the input buffer
+ * This routine handle the I18N transcoding to internal UTF-8
+ * This is used when operating the parser in progressive (push) mode.
+ *
+ * Returns the number of chars read and stored in the buffer, or -1
+ *         in case of error.
+ */
+int
+xmlParserInputBufferPush(xmlParserInputBufferPtr in,
+	                 int len, const char *buf) {
+    int nbchars = 0;
+
+    if (len < 0) return(0);
+    if (in->encoder != NULL) {
+        /*
+	 * Store the data in the incoming raw buffer
+	 */
+        if (in->raw == NULL) {
+	    in->raw = xmlBufferCreate();
+	}
+	xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
+
+	/*
+	 * convert as much as possible to the parser reading buffer.
+	 */
+	nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
+	if (nbchars < 0) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlParserInputBufferPush: encoder error\n");
+	    return(-1);
+	}
+    } else {
+	nbchars = len;
+        xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
+    }
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext,
+	    "I/O: pushed %d chars, buffer %d/%d\n",
+            nbchars, in->buffer->use, in->buffer->size);
+#endif
+    return(nbchars);
+}
+
+/**
+ * xmlParserInputBufferGrow:
+ * @in:  a buffered parser input
+ * @len:  indicative value of the amount of chars to read
+ *
+ * Grow up the content of the input buffer, the old data are preserved
+ * This routine handle the I18N transcoding to internal UTF-8
+ * This routine is used when operating the parser in normal (pull) mode
+ *
+ * TODO: one should be able to remove one extra copy by copying directy
+ *       onto in->buffer or in->raw
+ *
+ * Returns the number of chars read and stored in the buffer, or -1
+ *         in case of error.
+ */
+int
+xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
+    char *buffer = NULL;
+    int res = 0;
+    int nbchars = 0;
+    int buffree;
+
+    if ((len <= MINLEN) && (len != 4)) 
+        len = MINLEN;
+    buffree = in->buffer->size - in->buffer->use;
+    if (buffree <= 0) {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlParserInputBufferGrow : buffer full !\n");
+	return(0);
+    }
+    if (len > buffree) 
+        len = buffree;
+
+    buffer = (char *) xmlMalloc((len + 1) * sizeof(char));
+    if (buffer == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlParserInputBufferGrow : out of memory !\n");
+	return(-1);
+    }
+
+    /*
+     * Call the read method for this I/O type.
+     */
+    if (in->readcallback != NULL) {
+	res = in->readcallback(in->context, &buffer[0], len);
+    } else {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlParserInputBufferGrow : no input !\n");
+	xmlFree(buffer);
+	return(-1);
+    }
+    if (res < 0) {
+	perror ("read error");
+	xmlFree(buffer);
+	return(-1);
+    }
+    len = res;
+    if (in->encoder != NULL) {
+        /*
+	 * Store the data in the incoming raw buffer
+	 */
+        if (in->raw == NULL) {
+	    in->raw = xmlBufferCreate();
+	}
+	xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
+
+	/*
+	 * convert as much as possible to the parser reading buffer.
+	 */
+	nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
+	if (nbchars < 0) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlParserInputBufferGrow: encoder error\n");
+	    return(-1);
+	}
+    } else {
+	nbchars = len;
+        buffer[nbchars] = 0;
+        xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
+    }
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext,
+	    "I/O: read %d chars, buffer %d/%d\n",
+            nbchars, in->buffer->use, in->buffer->size);
+#endif
+    xmlFree(buffer);
+    return(nbchars);
+}
+
+/**
+ * xmlParserInputBufferRead:
+ * @in:  a buffered parser input
+ * @len:  indicative value of the amount of chars to read
+ *
+ * Refresh the content of the input buffer, the old data are considered
+ * consumed
+ * This routine handle the I18N transcoding to internal UTF-8
+ *
+ * Returns the number of chars read and stored in the buffer, or -1
+ *         in case of error.
+ */
+int
+xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
+    /* xmlBufferEmpty(in->buffer); */
+    if (in->readcallback != NULL)
+	return(xmlParserInputBufferGrow(in, len));
+    else
+        return(-1);
+}
+
+/**
+ * xmlOutputBufferWrite:
+ * @out:  a buffered parser output
+ * @len:  the size in bytes of the array.
+ * @buf:  an char array
+ *
+ * Write the content of the array in the output I/O buffer
+ * This routine handle the I18N transcoding from internal UTF-8
+ * The buffer is lossless, i.e. will store in case of partial
+ * or delayed writes.
+ *
+ * Returns the number of chars immediately written, or -1
+ *         in case of error.
+ */
+int
+xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
+    int nbchars = 0; /* number of chars to output to I/O */
+    int ret;         /* return from function call */
+    int written = 0; /* number of char written to I/O so far */
+    int chunk;       /* number of byte curreent processed from buf */
+
+    if (len < 0) return(0);
+
+    do {
+	chunk = len;
+	if (chunk > 4 * MINLEN)
+	    chunk = 4 * MINLEN;
+
+	/*
+	 * first handle encoding stuff.
+	 */
+	if (out->encoder != NULL) {
+	    /*
+	     * Store the data in the incoming raw buffer
+	     */
+	    if (out->conv == NULL) {
+		out->conv = xmlBufferCreate();
+	    }
+	    xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
+
+	    if ((out->buffer->use < MINLEN) && (chunk == len))
+		goto done;
+
+	    /*
+	     * convert as much as possible to the parser reading buffer.
+	     */
+	    ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+	    if (ret < 0) {
+		xmlGenericError(xmlGenericErrorContext,
+			"xmlOutputBufferWrite: encoder error\n");
+		return(-1);
+	    }
+	    nbchars = out->conv->use;
+	} else {
+	    xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
+	    nbchars = out->buffer->use;
+	}
+	buf += chunk;
+	len -= chunk;
+
+	if ((nbchars < MINLEN) && (len <= 0))
+	    goto done;
+
+	if (out->writecallback) {
+	    /*
+	     * second write the stuff to the I/O channel
+	     */
+	    if (out->encoder != NULL) {
+		ret = out->writecallback(out->context, 
+				 (const char *)out->conv->content, nbchars);
+		if (ret >= 0)
+		    xmlBufferShrink(out->conv, nbchars);
+	    } else {
+		ret = out->writecallback(out->context, 
+				 (const char *)out->buffer->content, nbchars);
+		if (ret >= 0)
+		    xmlBufferShrink(out->buffer, nbchars);
+	    }
+	    if (ret < 0) {
+		xmlGenericError(xmlGenericErrorContext,
+			"I/O: error %d writing %d bytes\n", ret, nbchars);
+		return(ret);
+	    }
+	    out->written += ret;
+	}
+	written += nbchars;
+    } while (len > 0);
+
+done:
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext,
+	    "I/O: wrote %d chars\n", written);
+#endif
+    return(written);
+}
+
+/**
+ * xmlOutputBufferWriteString:
+ * @out:  a buffered parser output
+ * @str:  a zero terminated C string
+ *
+ * Write the content of the string in the output I/O buffer
+ * This routine handle the I18N transcoding from internal UTF-8
+ * The buffer is lossless, i.e. will store in case of partial
+ * or delayed writes.
+ *
+ * Returns the number of chars immediately written, or -1
+ *         in case of error.
+ */
+int
+xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
+    int len;
+    
+    if (str == NULL)
+        return(-1);
+    len = strlen(str);
+
+    if (len > 0)
+	return(xmlOutputBufferWrite(out, len, str));
+    return(len);
+}
+
+/**
+ * xmlOutputBufferFlush:
+ * @out:  a buffered output
+ *
+ * flushes the output I/O channel
+ *
+ * Returns the number of byte written or -1 in case of error.
+ */
+int
+xmlOutputBufferFlush(xmlOutputBufferPtr out) {
+    int nbchars = 0, ret = 0;
+
+    /*
+     * first handle encoding stuff.
+     */
+    if ((out->conv != NULL) && (out->encoder != NULL)) {
+	/*
+	 * convert as much as possible to the parser reading buffer.
+	 */
+	nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+	if (nbchars < 0) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlOutputBufferWrite: encoder error\n");
+	    return(-1);
+	}
+    }
+
+    /*
+     * second flush the stuff to the I/O channel
+     */
+    if ((out->conv != NULL) && (out->encoder != NULL) &&
+	(out->writecallback != NULL)) {
+	ret = out->writecallback(out->context,
+	           (const char *)out->conv->content, out->conv->use);
+	if (ret >= 0)
+	    xmlBufferShrink(out->conv, ret);
+    } else if (out->writecallback != NULL) {
+	ret = out->writecallback(out->context,
+	           (const char *)out->buffer->content, out->buffer->use);
+	if (ret >= 0)
+	    xmlBufferShrink(out->buffer, ret);
+    }
+    if (ret < 0) {
+        xmlGenericError(xmlGenericErrorContext,
+		"I/O: error %d flushing %d bytes\n", ret, nbchars);
+	return(ret);
+    }
+    out->written += ret;
+
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext,
+	    "I/O: flushed %d chars\n", ret);
+#endif
+    return(ret);
+}
+
+/*
+ * xmlParserGetDirectory:
+ * @filename:  the path to a file
+ *
+ * lookup the directory for that file
+ *
+ * Returns a new allocated string containing the directory, or NULL.
+ */
+char *
+xmlParserGetDirectory(const char *filename) {
+    char *ret = NULL;
+    char dir[1024];
+    char *cur;
+    char sep = '/';
+
+    if (xmlInputCallbackInitialized == 0)
+	xmlRegisterDefaultInputCallbacks();
+
+    if (filename == NULL) return(NULL);
+#ifdef WIN32
+    sep = '\\';
+#endif
+
+    strncpy(dir, filename, 1023);
+    dir[1023] = 0;
+    cur = &dir[strlen(dir)];
+    while (cur > dir) {
+         if (*cur == sep) break;
+	 cur --;
+    }
+    if (*cur == sep) {
+        if (cur == dir) dir[1] = 0;
+	else *cur = 0;
+	ret = xmlMemStrdup(dir);
+    } else {
+        if (getcwd(dir, 1024) != NULL) {
+	    dir[1023] = 0;
+	    ret = xmlMemStrdup(dir);
+	}
+    }
+    return(ret);
+}
+
+/****************************************************************
+ *								*
+ *		External entities loading			*
+ *								*
+ ****************************************************************/
+
+/*
+ * xmlDefaultExternalEntityLoader:
+ * @URL:  the URL for the entity to load
+ * @ID:  the System ID for the entity to load
+ * @ctxt:  the context in which the entity is called or NULL
+ *
+ * By default we don't load external entitites, yet.
+ *
+ * Returns a new allocated xmlParserInputPtr, or NULL.
+ */
+static
+xmlParserInputPtr
+xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
+                               xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr ret = NULL;
+
+#ifdef DEBUG_EXTERNAL_ENTITIES
+    xmlGenericError(xmlGenericErrorContext,
+	    "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
+#endif
+    if (URL == NULL) {
+        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt,
+		    "failed to load external entity \"%s\"\n", ID);
+        return(NULL);
+    }
+    ret = xmlNewInputFromFile(ctxt, URL);
+    if (ret == NULL) {
+        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt,
+		    "failed to load external entity \"%s\"\n", URL);
+    }
+    return(ret);
+}
+
+static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
+       xmlDefaultExternalEntityLoader;
+
+/*
+ * xmlSetExternalEntityLoader:
+ * @f:  the new entity resolver function
+ *
+ * Changes the defaultexternal entity resolver function for the application
+ */
+void
+xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
+    xmlCurrentExternalEntityLoader = f;
+}
+
+/*
+ * xmlGetExternalEntityLoader:
+ *
+ * Get the default external entity resolver function for the application
+ *
+ * Returns the xmlExternalEntityLoader function pointer
+ */
+xmlExternalEntityLoader
+xmlGetExternalEntityLoader(void) {
+    return(xmlCurrentExternalEntityLoader);
+}
+
+/*
+ * xmlLoadExternalEntity:
+ * @URL:  the URL for the entity to load
+ * @ID:  the System ID for the entity to load
+ * @ctxt:  the context in which the entity is called or NULL
+ *
+ * Load an external entity, note that the use of this function for
+ * unparsed entities may generate problems
+ * TODO: a more generic External entitiy API must be designed
+ *
+ * Returns the xmlParserInputPtr or NULL
+ */
+xmlParserInputPtr
+xmlLoadExternalEntity(const char *URL, const char *ID,
+                      xmlParserCtxtPtr ctxt) {
+    return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
+}
+