xml/libxml2libs/src/libxml2/libxml2_xmlio.c
changeset 0 e35f40988205
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xml/libxml2libs/src/libxml2/libxml2_xmlio.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,3723 @@
+/*
+ * libxml2_xmlio.c : implementation of the I/O interfaces used by the parser
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ *
+ * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
+ * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
+ */
+
+#define IN_LIBXML
+#include "xmlenglibxml.h"
+
+#include <string.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <stdio.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
+     /* MS C library seems to define stat and _stat. The definition
+        is identical. Still, mapping them to each other causes a warning. */
+#    ifndef _MSC_VER
+#      define stat(x,y) _stat(x,y)
+#    endif
+#    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 <stdapis/libxml2/libxml2_parserinternals.h>
+#include "libxml2_errencoding.h"
+#include "libxml2_xmlerror2.h"
+#include <stdapis/libxml2/libxml2_uri.h>
+
+#ifdef LIBXML_CATALOG_ENABLED
+#include "libxml2_catalog.h"
+#endif
+
+#include <stdapis/libxml2/libxml2_globals.h>
+
+/* #define VERBOSE_FAILURE */
+/* #define DEBUG_EXTERNAL_ENTITIES */
+/* #define DEBUG_INPUT */
+
+#ifdef DEBUG_INPUT
+#define MINLEN 40
+#else
+#define MINLEN 4000
+#endif
+
+
+/************************************************************************
+ *                                                                      *
+ *      Tree memory error handler                                       *
+ *                                                                      *
+ ************************************************************************/
+
+#ifndef XMLENGINE_EXCLUDE_EMBED_MSG
+const char * const  IOerr[] = {
+    EMBED_ERRTXT("Unknown IO error"),                   /* UNKNOWN */
+    EMBED_ERRTXT("Permission denied"),                  /* EACCES */
+    EMBED_ERRTXT("Resource temporarily unavailable"),   /* EAGAIN */
+    EMBED_ERRTXT("Bad file descriptor"),                /* EBADF */
+    EMBED_ERRTXT("Bad message"),                        /* EBADMSG */
+    EMBED_ERRTXT("Resource busy"),                      /* EBUSY */
+    EMBED_ERRTXT("Operation canceled"),                 /* ECANCELED */
+    EMBED_ERRTXT("No child processes"),                 /* ECHILD */
+    EMBED_ERRTXT("Resource deadlock avoided"),          /* EDEADLK */
+    EMBED_ERRTXT("Domain error"),                       /* EDOM */
+    EMBED_ERRTXT("File exists"),                        /* EEXIST */
+    EMBED_ERRTXT("Bad address"),                        /* EFAULT */
+    EMBED_ERRTXT("File too large"),                     /* EFBIG */
+    EMBED_ERRTXT("Operation in progress"),              /* EINPROGRESS */
+    EMBED_ERRTXT("Interrupted function call"),          /* EINTR */
+    EMBED_ERRTXT("Invalid argument"),                   /* EINVAL */
+    EMBED_ERRTXT("Input/output error"),                 /* EIO */
+    EMBED_ERRTXT("Is a directory"),                     /* EISDIR */
+    EMBED_ERRTXT("Too many open files"),                /* EMFILE */
+    EMBED_ERRTXT("Too many links"),                     /* EMLINK */
+    EMBED_ERRTXT("Inappropriate message buffer length"),/* EMSGSIZE */
+    EMBED_ERRTXT("Filename too long"),                  /* ENAMETOOLONG */
+    EMBED_ERRTXT("Too many open files in system"),      /* ENFILE */
+    EMBED_ERRTXT("No such device"),                     /* ENODEV */
+    EMBED_ERRTXT("No such file or directory"),          /* ENOENT */
+    EMBED_ERRTXT("Exec format error"),                  /* ENOEXEC */
+    EMBED_ERRTXT("No locks available"),                 /* ENOLCK */
+    EMBED_ERRTXT("Not enough space"),                   /* ENOMEM */
+    EMBED_ERRTXT("No space left on device"),            /* ENOSPC */
+    EMBED_ERRTXT("Function not implemented"),           /* ENOSYS */
+    EMBED_ERRTXT("Not a directory"),                    /* ENOTDIR */
+    EMBED_ERRTXT("Directory not empty"),                /* ENOTEMPTY */
+    EMBED_ERRTXT("Not supported"),                      /* ENOTSUP */
+    EMBED_ERRTXT("Inappropriate I/O control operation"),/* ENOTTY */
+    EMBED_ERRTXT("No such device or address"),          /* ENXIO */
+    EMBED_ERRTXT("Operation not permitted"),            /* EPERM */
+    EMBED_ERRTXT("Broken pipe"),                        /* EPIPE */
+    EMBED_ERRTXT("Result too large"),                   /* ERANGE */
+    EMBED_ERRTXT("Read-only file system"),              /* EROFS */
+    EMBED_ERRTXT("Invalid seek"),                       /* ESPIPE */
+    EMBED_ERRTXT("No such process"),                    /* ESRCH */
+    EMBED_ERRTXT("Operation timed out"),                /* ETIMEDOUT */
+    EMBED_ERRTXT("Improper link"),                      /* EXDEV */
+    EMBED_ERRTXT("Attempt to load network entity %s"),  /* XML_IO_NETWORK_ATTEMPT */
+    EMBED_ERRTXT("encoder error"),                      /* XML_IO_ENCODER */
+    EMBED_ERRTXT("flush error"),
+    EMBED_ERRTXT("write error"),
+    EMBED_ERRTXT("no input"),
+    EMBED_ERRTXT("buffer full"),
+    EMBED_ERRTXT("loading error"),
+    EMBED_ERRTXT("not a socket"),                       /* ENOTSOCK */
+    EMBED_ERRTXT("already connected"),                  /* EISCONN */
+    EMBED_ERRTXT("connection refuxed"),                 /* ECONNREFUSED */
+    EMBED_ERRTXT("unreachable network"),                /* ENETUNREACH */
+    EMBED_ERRTXT("adddress in use"),                    /* EADDRINUSE */
+    EMBED_ERRTXT("already in use"),                     /* EALREADY */
+    EMBED_ERRTXT("unknown address familly")             /* EAFNOSUPPORT */
+};
+#endif /* ! XMLENGINE_EXCLUDE_EMBED_MSG */
+
+/**
+ * xmlIOErrMemory:
+ * @param extra extra informations
+ *
+ * Handle an out of memory condition
+ */
+static void
+xmlIOErrMemory(const char *extra)
+{
+    __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
+}
+
+/**
+ * __xmlIOErr:
+ * @param code the error number
+ * @
+ * @param extra extra informations
+ *
+ * Handle an I/O error
+ */
+void
+__xmlIOErr(int domain, int code, const char *extra)
+{
+    // Note: on Symbian 'errno' is a macro for function call
+    int _errno = errno;
+    if (code == 0) {
+#ifdef HAVE_ERRNO_H
+    if (_errno == 0) code = 0;
+#ifdef EACCES
+        else if (_errno == EACCES) code = XML_IO_EACCES;
+#endif
+#ifdef EAGAIN
+        else if (_errno == EAGAIN) code = XML_IO_EAGAIN;
+#endif
+#ifdef EBADF
+        else if (_errno == EBADF) code = XML_IO_EBADF;
+#endif
+#ifdef EBADMSG
+        else if (_errno == EBADMSG) code = XML_IO_EBADMSG;
+#endif
+#ifdef EBUSY
+        else if (_errno == EBUSY) code = XML_IO_EBUSY;
+#endif
+#ifdef ECANCELED
+        else if (_errno == ECANCELED) code = XML_IO_ECANCELED;
+#endif
+#ifdef ECHILD
+        else if (_errno == ECHILD) code = XML_IO_ECHILD;
+#endif
+#ifdef EDEADLK
+        else if (_errno == EDEADLK) code = XML_IO_EDEADLK;
+#endif
+#ifdef EDOM
+        else if (_errno == EDOM) code = XML_IO_EDOM;
+#endif
+#ifdef EEXIST
+        else if (_errno == EEXIST) code = XML_IO_EEXIST;
+#endif
+#ifdef EFAULT
+        else if (_errno == EFAULT) code = XML_IO_EFAULT;
+#endif
+#ifdef EFBIG
+        else if (_errno == EFBIG) code = XML_IO_EFBIG;
+#endif
+#ifdef EINPROGRESS
+        else if (_errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
+#endif
+#ifdef EINTR
+        else if (_errno == EINTR) code = XML_IO_EINTR;
+#endif
+#ifdef EINVAL
+        else if (_errno == EINVAL) code = XML_IO_EINVAL;
+#endif
+#ifdef EIO
+        else if (_errno == EIO) code = XML_IO_EIO;
+#endif
+#ifdef EISDIR
+        else if (_errno == EISDIR) code = XML_IO_EISDIR;
+#endif
+#ifdef EMFILE
+        else if (_errno == EMFILE) code = XML_IO_EMFILE;
+#endif
+#ifdef EMLINK
+        else if (_errno == EMLINK) code = XML_IO_EMLINK;
+#endif
+#ifdef EMSGSIZE
+        else if (_errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
+#endif
+#ifdef ENAMETOOLONG
+        else if (_errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
+#endif
+#ifdef ENFILE
+        else if (_errno == ENFILE) code = XML_IO_ENFILE;
+#endif
+#ifdef ENODEV
+        else if (_errno == ENODEV) code = XML_IO_ENODEV;
+#endif
+#ifdef ENOENT
+        else if (_errno == ENOENT) code = XML_IO_ENOENT;
+#endif
+#ifdef ENOEXEC
+        else if (_errno == ENOEXEC) code = XML_IO_ENOEXEC;
+#endif
+#ifdef ENOLCK
+        else if (_errno == ENOLCK) code = XML_IO_ENOLCK;
+#endif
+#ifdef ENOMEM
+        else if (_errno == ENOMEM) code = XML_IO_ENOMEM;
+#endif
+#ifdef ENOSPC
+        else if (_errno == ENOSPC) code = XML_IO_ENOSPC;
+#endif
+#ifdef ENOSYS
+        else if (_errno == ENOSYS) code = XML_IO_ENOSYS;
+#endif
+#ifdef ENOTDIR
+        else if (_errno == ENOTDIR) code = XML_IO_ENOTDIR;
+#endif
+#ifdef ENOTEMPTY
+        else if (_errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
+#endif
+#ifdef ENOTSUP
+        else if (_errno == ENOTSUP) code = XML_IO_ENOTSUP;
+#endif
+#ifdef ENOTTY
+        else if (_errno == ENOTTY) code = XML_IO_ENOTTY;
+#endif
+#ifdef ENXIO
+        else if (_errno == ENXIO) code = XML_IO_ENXIO;
+#endif
+#ifdef EPERM
+        else if (_errno == EPERM) code = XML_IO_EPERM;
+#endif
+#ifdef EPIPE
+        else if (_errno == EPIPE) code = XML_IO_EPIPE;
+#endif
+#ifdef ERANGE
+        else if (_errno == ERANGE) code = XML_IO_ERANGE;
+#endif
+#ifdef EROFS
+        else if (_errno == EROFS) code = XML_IO_EROFS;
+#endif
+#ifdef ESPIPE
+        else if (_errno == ESPIPE) code = XML_IO_ESPIPE;
+#endif
+#ifdef ESRCH
+        else if (_errno == ESRCH) code = XML_IO_ESRCH;
+#endif
+#ifdef ETIMEDOUT
+        else if (_errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
+#endif
+#ifdef EXDEV
+        else if (_errno == EXDEV) code = XML_IO_EXDEV;
+#endif
+#ifdef ENOTSOCK
+        else if (_errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
+#endif
+#ifdef EISCONN
+        else if (_errno == EISCONN) code = XML_IO_EISCONN;
+#endif
+#ifdef ECONNREFUSED
+        else if (_errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
+#endif
+#ifdef ETIMEDOUT
+        else if (_errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
+#endif
+#ifdef ENETUNREACH
+        else if (_errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
+#endif
+#ifdef EADDRINUSE
+        else if (_errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
+#endif
+#ifdef EINPROGRESS
+        else if (_errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
+#endif
+#ifdef EALREADY
+        else if (_errno == EALREADY) code = XML_IO_EALREADY;
+#endif
+#ifdef EAFNOSUPPORT
+        else if (_errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
+#endif
+        else code = XML_IO_UNKNOWN;
+#endif /* HAVE_ERRNO_H */
+    }
+
+#if defined(LIBXML_OUTPUT_ENABLED) && !defined(XMLENGINE_EXCLUDE_EMBED_MSG)
+    {
+    unsigned int idx = 0;
+    if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
+
+    // DONE: disable this branch if error messages are stripped from sources (and then disable IOerr array too)
+    if (idx >= (sizeof(IOerr) / sizeof(IOerr[0])))
+        idx = 0;
+    __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
+    }
+#else
+    // No error messages used..
+    __xmlSimpleError(domain, code, NULL, EMBED_ERRTXT("IOError"), extra);
+#endif /* LIBXML_OUTPUT_ENABLED */
+}
+
+/**
+ * xmlIOErr:
+ * @param code the error number
+ * @param extra extra informations
+ *
+ * Handle an I/O error
+ */
+static void
+xmlIOErr(int code, const char *extra)
+{
+    __xmlIOErr(XML_FROM_IO, code, extra);
+}
+
+/**
+ * __xmlLoaderErr:
+ * @param ctx the parser context
+ * @param extra extra informations
+ *
+ * Handle a resource access error
+ */
+void
+__xmlLoaderErr(void *ctx, const char *msg, const char *filename)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlStructuredErrorFunc schannel = NULL;
+    xmlGenericErrorFunc channel = NULL;
+    void *data = NULL;
+    xmlErrorLevel level = XML_ERR_ERROR;
+
+    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
+        (ctxt->instate == XML_PARSER_EOF))
+    return;
+    if ((ctxt != NULL) && (ctxt->sax != NULL)) {
+        if (ctxt->validate) {
+        channel = ctxt->sax->error;
+        level = XML_ERR_ERROR;
+    } else {
+        channel = ctxt->sax->warning;
+        level = XML_ERR_WARNING;
+    }
+    schannel = ctxt->sax->serror;
+    data = ctxt->userData;
+    }
+    __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
+                    XML_IO_LOAD_ERROR, level, NULL, 0,
+            filename, NULL, NULL, 0, 0,
+            msg, filename);
+
+}
+
+/************************************************************************
+ *                                                                      *
+ *      Tree memory error handler                                       *
+ *                                                                      *
+ ************************************************************************/
+
+/**
+ * xmlCleanupInputCallbacks:
+ *
+ * clears the entire input callback table. this includes the
+ * compiled-in I/O.
+ *
+ * OOM: never
+ */
+XMLPUBFUNEXPORT void
+xmlCleanupInputCallbacks(void)
+{
+	LOAD_GS_DIRECT
+    int i;
+
+    if (!xmlInputCallbackInitialized)
+        return;
+    
+    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
+        xmlInputCallbackTable[i].matchcallback = NULL;
+        xmlInputCallbackTable[i].opencallback = NULL;
+        xmlInputCallbackTable[i].readcallback = NULL;
+        xmlInputCallbackTable[i].closecallback = NULL;
+    }
+
+    xmlInputCallbackNr = 0;
+    xmlInputCallbackInitialized = 0;
+}
+
+/**
+ * xmlPopInputCallback:
+ *
+ * Clear the top input callback from the input stack. this includes the
+ * compiled-in I/O.
+ *
+ * Returns the number of input callback registered or -1 in case of error.
+ */
+XMLPUBFUNEXPORT int
+xmlPopInputCallbacks(void)
+{
+	LOAD_GS_DIRECT
+    if (!xmlInputCallbackInitialized)
+        return(-1);
+
+    if (xmlInputCallbackNr <= 0)
+        return(-1);
+
+    xmlInputCallbackNr--;
+    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
+    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
+    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
+    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
+
+    return(xmlInputCallbackNr);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlCleanupOutputCallbacks:
+ *
+ * clears the entire output callback table. this includes the
+ * compiled-in I/O callbacks.
+ */
+XMLPUBFUNEXPORT void
+xmlCleanupOutputCallbacks(void)
+{
+	LOAD_GS_DIRECT
+    int i;
+
+    if (!xmlOutputCallbackInitialized)
+        return;
+
+    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
+        xmlOutputCallbackTable[i].matchcallback = NULL;
+        xmlOutputCallbackTable[i].opencallback = NULL;
+        xmlOutputCallbackTable[i].writecallback = NULL;
+        xmlOutputCallbackTable[i].closecallback = NULL;
+    }
+
+    xmlOutputCallbackNr = 0;
+    xmlOutputCallbackInitialized = 0;
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/************************************************************************
+ *                                                                      *
+ *      Standard I/O for file accesses                                  *
+ *                                                                      *
+ ************************************************************************/
+
+/**
+ * xmlCheckFilename:
+ * @param 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,
+ * returns 2.  otherwise returns 1.
+ */
+#include <sys/stat.h>
+XMLPUBFUNEXPORT int
+xmlCheckFilename (const char* path)
+{
+#ifdef HAVE_STAT
+    struct stat stat_buffer;
+
+    if (stat(path, &stat_buffer) == -1)
+        return 0;
+
+#ifdef S_ISDIR
+    if (S_ISDIR(stat_buffer.st_mode)) {
+        return 2;
+    }
+#endif
+#endif
+    return 1;
+}
+
+static int
+xmlNop(void) {
+    return(0);
+}
+
+/**
+ * xmlFdRead:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param len number of bytes to read
+ *
+ * Read len bytes to buffer from the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+static int
+xmlFdRead (void * context, char * buffer, int len) {
+    int ret;
+
+    ret = read((int) (long) context, &buffer[0], len);
+    if (ret < 0) xmlIOErr(0, EMBED_ERRTXT("read()"));
+    return(ret);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlFdWrite:
+ * @param context the I/O context
+ * @param buffer where to get data
+ * @param len number of bytes to write
+ *
+ * Write len bytes from buffer to the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+static int
+xmlFdWrite (void * context, const char * buffer, int len) {
+    int ret;
+
+    ret = write((int) (long) context, &buffer[0], len);
+    if (ret < 0) xmlIOErr(0, "write()");
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlFdClose:
+ * @param context the I/O context
+ *
+ * Close an I/O channel
+ *
+ * Returns 0 in case of success and error code otherwise
+ */
+static int
+xmlFdClose (void * context) {
+    int ret;
+    ret = close((int) (long) context);
+    if (ret < 0) xmlIOErr(0, EMBED_ERRTXT("close()"));
+    return(ret);
+}
+
+/**
+ * xmlFileMatch:
+ * @param filename the URI for matching
+ *
+ * input from FILE *
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+XMLPUBFUNEXPORT int
+xmlFileMatch (const char* filename ATTRIBUTE_UNUSED) {
+    return(1);
+}
+
+// XMLENGINE: NEW CODE: xmlFileOpen_common
+//            --> common method extracted from xmlFileOpenW and xmlFileOpen_real;
+//            --> Slashes-handling code added for Symbian UREL builds
+/*
+ *
+ *
+ */
+static void*
+xmlFileOpen_common(const char* filename, const char* mode)
+{
+    FILE* fd;
+    char* p;
+    char* rpath;
+    const char* path = filename;
+
+    if (!path)
+        return(NULL);
+
+    if(filename[0] == 'f' && filename[1] == 'i')
+    {
+        if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
+            path = &filename[17];
+        else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8))
+            path = &filename[8];
+    }
+
+    // Convert all slashes into backslashes
+    
+    path = rpath = p = (char*) xmlStrdup((const xmlChar*) path);
+    if(!p)
+        return NULL; 
+
+    for(; *p; p++){
+        if(*p == '/')
+            *p = '\\';
+    }
+
+    fd = fopen(path, mode);
+    CHECK_ERRNO;
+
+    if (!fd){
+        xmlIOErr(0, path);
+    }
+
+    xmlFree(rpath);
+    return((void*) fd);
+}
+
+/**
+ * xmlFileOpen_real:
+ * @param 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
+ *
+ * OOM: possible --> OOM flag is set
+ */
+void*
+xmlFileOpen_real (const char* filename)
+{
+    if (filename && filename[0] == '-' && !filename[1])
+        return((void *) stdin);
+    else
+        return xmlFileOpen_common(filename, "r");  // Symbian case is here, right ?
+}
+
+/**
+ * xmlFileOpen:
+ * @param filename the URI for matching
+ *
+ * Wrapper around xmlFileOpen_real that try it with an unescaped
+ * version of filename, if this fails fallback to filename
+ *
+ * Returns a handler or NULL in case or failure
+ */
+XMLPUBFUNEXPORT void*
+xmlFileOpen (const char* filename) {
+    char* unescaped;
+    void* retval;
+
+    unescaped = xmlURIUnescapeString(filename, 0, NULL);
+    retval = xmlFileOpen_real(unescaped ? unescaped : filename);
+
+    if(unescaped)
+        xmlFree(unescaped);
+    return retval;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlFileOpenW:
+ * @param 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
+ *
+ * OOM: possible --> OOM flag is set
+ */
+static void*
+xmlFileOpenW (const char* filename)
+{
+    if (filename && filename[0] == '-' && !filename[1])
+        return((void*) stdout);
+    else
+        return xmlFileOpen_common(filename, "wb");
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+
+/**
+ * xmlFileRead:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param len number of bytes to write
+ *
+ * Read len bytes to buffer from the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+XMLPUBFUNEXPORT int
+xmlFileRead (void* context, char* buffer, int len)
+{
+    int ret = fread(&buffer[0], 1,  len, (FILE*) context);
+    if (ret < 0) {
+        CHECK_ERRNO;
+        xmlIOErr(0, EMBED_ERRTXT("fread()"));
+    }
+    return(ret);
+}
+
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlFileWrite:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param len number of bytes to write
+ *
+ * Write len bytes from buffer to the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+//static
+int
+xmlFileWrite (void* context, const char* buffer, int len)
+{
+    int items = fwrite(&buffer[0], len, 1, (FILE*) context);
+
+    if (items == EOF ||
+        (items == 0 && ferror((FILE*) context)))
+    {
+        CHECK_ERRNO;
+        xmlIOErr(0, EMBED_ERRTXT("fwrite()"));
+        return(-1);
+    }
+    return(items * len);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+
+
+/**
+ * xmlFileClose:
+ * @param context the I/O context
+ *
+ * Close an I/O channel
+ *
+ * Returns 0 or -1 in case of error
+ */
+XMLPUBFUNEXPORT int
+xmlFileClose (void* context)
+{
+    FILE* fil;
+    int ret;
+
+    fil = (FILE*) context;
+    if ((fil == stdout) || (fil == stderr)) {
+        ret = fflush(fil);
+        if (ret < 0){
+            CHECK_ERRNO;
+            xmlIOErr(0, EMBED_ERRTXT("fflush()"));
+        }
+        return(0);
+    }
+    if (fil == stdin)
+        return(0);
+    ret = ( fclose((FILE*) context) == EOF ) ? -1 : 0;
+    if (ret < 0){
+        CHECK_ERRNO;
+        xmlIOErr(0, EMBED_ERRTXT("fclose()"));
+    }
+    return(ret);
+}
+
+/**
+ * xmlFileFlush:
+ * @param context the I/O context
+ *
+ * Flush an I/O channel
+ */
+static int
+xmlFileFlush (void * context)
+{
+    int ret = (fflush((FILE *) context) == EOF) ? -1 : 0;
+    if (ret < 0){
+        CHECK_ERRNO;
+        xmlIOErr(0, EMBED_ERRTXT("fflush()"));
+    }
+    return(ret);
+}
+
+
+#ifdef HAVE_ZLIB_H
+/************************************************************************
+ *                                                                      *
+ *      I/O for compressed file accesses                                *
+ *                                                                      *
+ ************************************************************************/
+/**
+ * xmlGzfileMatch:
+ * @param filename the URI for matching
+ *
+ * input from compressed file test
+ *
+ * Returns 1 if matches, 0 otherwise
+ */
+static int
+xmlGzfileMatch (const char* filename ATTRIBUTE_UNUSED)
+{
+    return(1);
+}
+
+/**
+ * xmlGzfileOpen_real:
+ * @param 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
+ */
+static void*
+xmlGzfileOpen_real (const char *filename)
+{
+    const char *path = NULL;
+    gzFile fd;
+
+    if (!strcmp(filename, "-")) {
+        fd = gzdopen(dup(0), "rb");
+        return((void *) fd);
+    }
+
+    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
+        path = &filename[17];
+    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
+        path = &filename[8];
+    } else
+        path = filename;
+
+    if (path == NULL)
+    return(NULL);
+    if (!xmlCheckFilename(path))
+        return(NULL);
+
+    fd = gzopen(path, "rb");
+    return((void *) fd);
+}
+
+/**
+ * xmlGzfileOpen:
+ * @param filename the URI for matching
+ *
+ * Wrapper around xmlGzfileOpen if the open fais, it will
+ * try to unescape filename
+ */
+static void*
+xmlGzfileOpen (const char* filename)
+{
+    char* unescaped;
+    void* retval;
+
+    retval = xmlGzfileOpen_real(filename);
+    if (retval == NULL) {
+        unescaped = xmlURIUnescapeString(filename, 0, NULL);
+        if (unescaped != NULL) {
+            retval = xmlGzfileOpen_real(unescaped);
+        }
+        xmlFree(unescaped);
+    }
+    return retval;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlGzfileOpenW:
+ * @param filename the URI for matching
+ * @param 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
+ */
+static void*
+xmlGzfileOpenW (const char *filename, int compression)
+{
+    const char* path = NULL;
+    char mode[15];
+    gzFile fd;
+
+    snprintf(mode, sizeof(mode), "wb%d", compression);
+    if (!strcmp(filename, "-")) {
+        fd = gzdopen(dup(1), mode);
+    return((void *) fd);
+    }
+
+    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
+        path = &filename[17];
+    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
+        path = &filename[8];
+    } else
+        path = filename;
+
+    if (path == NULL)
+        return(NULL);
+
+    fd = gzopen(path, mode);
+    return((void *) fd);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlGzfileRead:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param len number of bytes to write
+ *
+ * Read len bytes to buffer from the compressed I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+static int
+xmlGzfileRead (void * context, char * buffer, int len)
+{
+    int ret;
+
+    ret = gzread((gzFile) context, &buffer[0], len);
+    if (ret < 0) xmlIOErr(0, EMBED_ERRTXT("gzread()"));
+    return(ret);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlGzfileWrite:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param len number of bytes to write
+ *
+ * Write len bytes from buffer to the compressed I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+static int
+xmlGzfileWrite (void * context, const char * buffer, int len)
+{
+    int ret;
+
+    ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
+    if (ret < 0) xmlIOErr(0, EMBED_ERRTXT("gzwrite()"));
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlGzfileClose:
+ * @param context the I/O context
+ *
+ * Close a compressed I/O channel
+ */
+static int
+xmlGzfileClose (void * context)
+{
+    int ret;
+
+    ret =  (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
+    if (ret < 0) xmlIOErr(0, EMBED_ERRTXT("gzclose()"));
+    return(ret);
+}
+#endif /* HAVE_ZLIB_H */
+
+#ifdef LIBXML_HTTP_ENABLED
+/************************************************************************
+ *                                  *
+ *          I/O for HTTP file accesses          *
+ *                                  *
+ ************************************************************************/
+
+#ifdef LIBXML_OUTPUT_ENABLED
+typedef struct xmlIOHTTPWriteCtxt_
+{
+    int         compression;
+    char *      uri;
+    void *      doc_buff;
+} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
+
+#ifdef HAVE_ZLIB_H
+
+#define DFLT_WBITS      ( -15 )
+#define DFLT_MEM_LVL        ( 8 )
+#define GZ_MAGIC1       ( 0x1f )
+#define GZ_MAGIC2       ( 0x8b )
+#define LXML_ZLIB_OS_CODE   ( 0x03 )
+#define INIT_HTTP_BUFF_SIZE ( 32768 )
+#define DFLT_ZLIB_RATIO     ( 5 )
+
+/*
+**  Data structure and functions to work with sending compressed data
+**  via HTTP.
+*/
+
+typedef struct xmlZMemBuff_
+{
+   unsigned long    size;
+   unsigned long    crc;
+   unsigned char *  zbuff;
+   z_stream     zctrl;
+
+} xmlZMemBuff, *xmlZMemBuffPtr;
+
+/**
+ * append_reverse_ulong
+ * @param buff Compressed memory buffer
+ * @param data Unsigned long to append
+ *
+ * Append a unsigned long in reverse byte order to the end of the
+ * memory buffer.
+ */
+static void
+append_reverse_ulong( xmlZMemBuff * buff, unsigned long data )
+{
+    int     idx;
+
+    if ( buff == NULL )
+    return;
+
+    /*
+    **  This is plagiarized from putLong in gzio.c (zlib source) where
+    **  the number "4" is hardcoded.  If zlib is ever patched to
+    **  support 64 bit file sizes, this code would need to be patched
+    **  as well.
+    */
+
+    for ( idx = 0; idx < 4; idx++ ) {
+    *buff->zctrl.next_out = ( data & 0xff );
+    data >>= 8;
+    buff->zctrl.next_out++;
+    }
+
+    return;
+}
+
+/**
+ *
+ * xmlFreeZMemBuff
+ * @param buff The memory buffer context to clear
+ *
+ * Release all the resources associated with the compressed memory buffer.
+ */
+static void
+xmlFreeZMemBuff( xmlZMemBuffPtr buff )
+{
+#ifdef DEBUG_HTTP
+    int z_err;
+#endif
+
+    if ( buff == NULL )
+    return;
+
+    xmlFree( buff->zbuff );
+#ifdef DEBUG_HTTP
+    z_err = deflateEnd( &buff->zctrl );
+    if ( z_err != Z_OK )
+    xmlGenericError( xmlGenericErrorContext,
+            EMBED_ERRTXT("xmlFreeZMemBuff:  Error releasing zlib context:  %d\n"),
+            z_err );
+#else
+    deflateEnd( &buff->zctrl );
+#endif
+
+    xmlFree( buff );
+    return;
+}
+
+/**
+ * xmlCreateZMemBuff
+ *@param compression Compression value to use
+ *
+ * Create a memory buffer to hold the compressed XML document.  The
+ * compressed document in memory will end up being identical to what
+ * would be created if gzopen/gzwrite/gzclose were being used to
+ * write the document to disk.  The code for the header/trailer data to
+ * the compression is plagiarized from the zlib source files.
+ */
+static void *
+xmlCreateZMemBuff( int compression )
+{
+    int         z_err;
+    int         hdr_lgth;
+    xmlZMemBuffPtr  buff = NULL;
+
+    if ( ( compression < 1 ) || ( compression > 9 ) )
+    return ( NULL );
+
+    /*  Create the control and data areas  */
+
+    buff = xmlMalloc( sizeof( xmlZMemBuff ) );
+    if ( buff == NULL ) {
+    xmlIOErrMemory(EMBED_ERRTXT("creating buffer context"));
+    return ( NULL );
+    }
+
+    (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
+    buff->size = INIT_HTTP_BUFF_SIZE;
+    buff->zbuff = xmlMalloc( buff->size );
+    if ( buff->zbuff == NULL ) {
+    xmlFreeZMemBuff( buff );
+    xmlIOErrMemory(EMBED_ERRTXT("creating buffer"));
+    return ( NULL );
+    }
+
+    z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
+                DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
+    if ( z_err != Z_OK ) {
+    xmlChar msg[500];
+    xmlFreeZMemBuff( buff );
+    buff = NULL;
+    xmlStrPrintf(msg, 500,
+            (const xmlChar *) EMBED_ERRTXT("xmlCreateZMemBuff:  %s %d\n"),
+            EMBED_ERRTXT("Error initializing compression context.  ZLIB error:"),
+            z_err );
+    xmlIOErr(XML_IO_WRITE, (const char *) msg);
+    return ( NULL );
+    }
+
+    /*  Set the header data.  The CRC will be needed for the trailer  */
+    buff->crc = crc32( 0L, Z_NULL, 0 );
+    hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
+            "%c%c%c%c%c%c%c%c%c%c",
+            GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
+            0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
+    buff->zctrl.next_out  = buff->zbuff + hdr_lgth;
+    buff->zctrl.avail_out = buff->size - hdr_lgth;
+
+    return ( buff );
+}
+
+/**
+ * xmlZMemBuffExtend
+ * @param buff Buffer used to compress and consolidate data.
+ * @param ext_amt Number of bytes to extend the buffer.
+ *
+ * Extend the internal buffer used to store the compressed data by the
+ * specified amount.
+ *
+ * Returns 0 on success or -1 on failure to extend the buffer.  On failure
+ * the original buffer still exists at the original size.
+ */
+static int
+xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt )
+{
+    int         rc = -1;
+    size_t      new_size;
+    size_t      cur_used;
+
+    unsigned char * tmp_ptr = NULL;
+
+    if ( buff == NULL )
+    return ( -1 );
+
+    else if ( ext_amt == 0 )
+    return ( 0 );
+
+    cur_used = buff->zctrl.next_out - buff->zbuff;
+    new_size = buff->size + ext_amt;
+
+#ifdef DEBUG_HTTP
+    if ( cur_used > new_size )
+    xmlGenericError( xmlGenericErrorContext,
+            "xmlZMemBuffExtend:  %s\n%s %d bytes.\n",
+            "Buffer overwrite detected during compressed memory",
+            "buffer extension.  Overflowed by",
+            (cur_used - new_size ) );
+#endif
+
+    tmp_ptr = xmlRealloc( buff->zbuff, new_size );
+    if ( tmp_ptr != NULL ) {
+    rc = 0;
+    buff->size  = new_size;
+    buff->zbuff = tmp_ptr;
+    buff->zctrl.next_out  = tmp_ptr + cur_used;
+    buff->zctrl.avail_out = new_size - cur_used;
+    }
+    else {
+    xmlChar msg[500];
+    xmlStrPrintf(msg, 500,
+            (const xmlChar *) EMBED_ERRTXT("xmlZMemBuffExtend:  %s %lu bytes.\n"),
+            EMBED_ERRTXT("Allocation failure extending output buffer to"),
+            new_size );
+    xmlIOErr(XML_IO_WRITE, (const char *) msg);
+    }
+
+    return ( rc );
+}
+
+/**
+ * xmlZMemBuffAppend
+ * @param buff Buffer used to compress and consolidate data
+ * @param src Uncompressed source content to append to buffer
+ * @param len Length of source data to append to buffer
+ *
+ * Compress and append data to the internal buffer.  The data buffer
+ * will be expanded if needed to store the additional data.
+ *
+ * Returns the number of bytes appended to the buffer or -1 on error.
+ */
+static int
+xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len )
+{
+    int     z_err;
+    size_t  min_accept;
+
+    if ( ( buff == NULL ) || ( src == NULL ) )
+    return ( -1 );
+
+    buff->zctrl.avail_in = len;
+    buff->zctrl.next_in  = (unsigned char *)src;
+    while ( buff->zctrl.avail_in > 0 ) {
+    /*
+    **  Extend the buffer prior to deflate call if a reasonable amount
+    **  of output buffer space is not available.
+    */
+    min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
+    if ( buff->zctrl.avail_out <= min_accept ) {
+        if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
+        return ( -1 );
+    }
+
+    z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
+    if ( z_err != Z_OK ) {
+        xmlChar msg[500];
+        xmlStrPrintf(msg, 500,
+            (const xmlChar *) EMBED_ERRTXT("xmlZMemBuffAppend:  %s %d %s - %d"),
+            EMBED_ERRTXT("Compression error while appending"),
+            len, EMBED_ERRTXT("bytes to buffer.  ZLIB error"), z_err );
+        xmlIOErr(XML_IO_WRITE, (const char *) msg);
+        return ( -1 );
+    }
+    }
+
+    buff->crc = crc32( buff->crc, (unsigned char *)src, len );
+
+    return ( len );
+}
+
+/**
+ * xmlZMemBuffGetContent
+ * @param buff Compressed memory content buffer
+ * @param data_ref Pointer reference to point to compressed content
+ *
+ * Flushes the compression buffers, appends gzip file trailers and
+ * returns the compressed content and length of the compressed data.
+ * NOTE:  The gzip trailer code here is plagiarized from zlib source.
+ *
+ * Returns the length of the compressed data or -1 on error.
+ */
+static int
+xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref )
+{
+    int     zlgth = -1;
+    int     z_err;
+
+    if ( ( buff == NULL ) || ( data_ref == NULL ) )
+    return ( -1 );
+
+    /*  Need to loop until compression output buffers are flushed  */
+
+    do
+    {
+    z_err = deflate( &buff->zctrl, Z_FINISH );
+    if ( z_err == Z_OK ) {
+        /*  In this case Z_OK means more buffer space needed  */
+
+        if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
+        return ( -1 );
+    }
+    }
+    while ( z_err == Z_OK );
+
+    /*  If the compression state is not Z_STREAM_END, some error occurred  */
+
+    if ( z_err == Z_STREAM_END ) {
+
+    /*  Need to append the gzip data trailer  */
+
+    if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
+        if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
+        return ( -1 );
+    }
+
+    /*
+    **  For whatever reason, the CRC and length data are pushed out
+    **  in reverse byte order.  So a memcpy can't be used here.
+    */
+
+    append_reverse_ulong( buff, buff->crc );
+    append_reverse_ulong( buff, buff->zctrl.total_in );
+
+    zlgth = buff->zctrl.next_out - buff->zbuff;
+    *data_ref = (char *)buff->zbuff;
+    }
+
+    else {
+    xmlChar msg[500];
+    xmlStrPrintf(msg, 500,
+            (const xmlChar *) EMBED_ERRTXT("xmlZMemBuffGetContent:  %s - %d\n"),
+            EMBED_ERRTXT("Error flushing zlib buffers.  Error code"), z_err );
+    xmlIOErr(XML_IO_WRITE, (const char *) msg);
+    }
+
+    return ( zlgth );
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+#endif  /*  HAVE_ZLIB_H  */
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlFreeHTTPWriteCtxt
+ * @param ctxt Context to cleanup
+ *
+ * Free allocated memory and reclaim system resources.
+ *
+ * No return value.
+ */
+static void
+xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
+{
+    if ( ctxt->uri != NULL )
+    xmlFree( ctxt->uri );
+
+    if ( ctxt->doc_buff != NULL ) {
+
+#ifdef HAVE_ZLIB_H
+    if ( ctxt->compression > 0 ) {
+        xmlFreeZMemBuff( ctxt->doc_buff );
+    }
+    else
+#endif
+    {
+        xmlOutputBufferClose( ctxt->doc_buff );
+    }
+    }
+
+    xmlFree( ctxt );
+    return;
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+
+/**
+ * xmlIOHTTPMatch:
+ * @param 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 (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
+    return(1);
+    return(0);
+}
+
+/**
+ * xmlIOHTTPOpen:
+ * @param 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));
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlIOHTTPOpenW:
+ * @param post_uri The destination URI for the document
+ * @param compression The compression desired for the document.
+ *
+ * Open a temporary buffer to collect the document for a subsequent HTTP POST
+ * request.  Non-static as is called from the output buffer creation routine.
+ *
+ * Returns an I/O context or NULL in case of error.
+ */
+
+void *
+xmlIOHTTPOpenW(const char *post_uri, int compression)
+{
+
+    xmlIOHTTPWriteCtxtPtr ctxt = NULL;
+
+    if (post_uri == NULL)
+        return (NULL);
+
+    ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
+    if (ctxt == NULL) {
+    xmlIOErrMemory(EMBED_ERRTXT("creating HTTP output context"));
+        return (NULL);
+    }
+
+    (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
+
+    ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
+    if (ctxt->uri == NULL) {
+    xmlIOErrMemory(EMBED_ERRTXT("copying URI"));
+        xmlFreeHTTPWriteCtxt(ctxt);
+        return (NULL);
+    }
+
+    /*
+     * **  Since the document length is required for an HTTP post,
+     * **  need to put the document into a buffer.  A memory buffer
+     * **  is being used to avoid pushing the data to disk and back.
+     */
+
+#ifdef HAVE_ZLIB_H
+    if ((compression > 0) && (compression <= 9)) {
+
+        ctxt->compression = compression;
+        ctxt->doc_buff = xmlCreateZMemBuff(compression);
+    } else
+#endif
+    {
+        /*  Any character conversions should have been done before this  */
+
+        ctxt->doc_buff = xmlAllocOutputBuffer(NULL);
+    }
+
+    if (ctxt->doc_buff == NULL) {
+        xmlFreeHTTPWriteCtxt(ctxt);
+        ctxt = NULL;
+    }
+
+    return (ctxt);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlIOHTTPDfltOpenW
+ * @param post_uri The destination URI for this document.
+ *
+ * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
+ * HTTP post command.  This function should generally not be used as
+ * the open callback is short circuited in xmlOutputBufferCreateFile.
+ *
+ * Returns a pointer to the new IO context.
+ */
+static void *
+xmlIOHTTPDfltOpenW( const char * post_uri )
+{
+    return ( xmlIOHTTPOpenW( post_uri, 0 ) );
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlIOHTTPRead:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param 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));
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlIOHTTPWrite
+ * @param context previously opened writing context
+ * @param buffer data to output to temporary buffer
+ * @param len bytes to output
+ *
+ * Collect data from memory buffer into a temporary file for later
+ * processing.
+ *
+ * Returns number of bytes written.
+ */
+
+static int
+xmlIOHTTPWrite( void * context, const char * buffer, int len )
+{
+    xmlIOHTTPWriteCtxtPtr   ctxt = context;
+
+    if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
+    return ( -1 );
+
+    if ( len > 0 ) {
+
+    /*  Use gzwrite or fwrite as previously setup in the open call  */
+
+#ifdef HAVE_ZLIB_H
+    if ( ctxt->compression > 0 )
+        len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
+
+    else
+#endif
+        len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
+
+    if ( len < 0 ) {
+        xmlChar msg[500];
+        xmlStrPrintf(msg, 500,
+            (const xmlChar *) EMBED_ERRTXT("xmlIOHTTPWrite:  %s\n%s '%s'.\n"),
+            EMBED_ERRTXT("Error appending to internal buffer."),
+            EMBED_ERRTXT("Error sending document to URI"),
+            ctxt->uri );
+        xmlIOErr(XML_IO_WRITE, (const char *) msg);
+    }
+    }
+
+    return ( len );
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+
+/**
+ * xmlIOHTTPClose:
+ * @param context the I/O context
+ *
+ * Close an HTTP I/O channel
+ *
+ * Returns 0
+ */
+int
+xmlIOHTTPClose (void * context)
+{
+    xmlNanoHTTPClose(context);
+    return 0;
+}
+
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlIOHTTCloseWrite
+ * @param context The I/O context
+ * @param http_mthd The HTTP method to be used when sending the data
+ *
+ * Close the transmit HTTP I/O channel and actually send the data.
+ */
+static int
+xmlIOHTTPCloseWrite( void * context, const char * http_mthd )
+{
+    int             close_rc = -1;
+    int             http_rtn = 0;
+    int             content_lgth = 0;
+    xmlIOHTTPWriteCtxtPtr   ctxt = context;
+
+    char *          http_content = NULL;
+    char *          content_encoding = NULL;
+    char *          content_type = (char *) "text/xml";
+    void *          http_ctxt = NULL;
+
+    if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
+    return ( -1 );
+
+    /*  Retrieve the content from the appropriate buffer  */
+
+#ifdef HAVE_ZLIB_H
+
+    if ( ctxt->compression > 0 ) {
+    content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
+    content_encoding = (char *) "Content-Encoding: gzip";
+    }
+    else
+#endif
+    {
+    /*  Pull the data out of the memory output buffer  */
+
+    xmlOutputBufferPtr  dctxt = ctxt->doc_buff;
+    http_content = (char *)dctxt->buffer->content;
+    content_lgth = dctxt->buffer->use;
+    }
+
+    if ( http_content == NULL ) {
+        xmlChar msg[500];
+        xmlStrPrintf(msg, 500,
+             (const xmlChar *) EMBED_ERRTXT("xmlIOHTTPCloseWrite:  %s '%s' %s '%s'.\n"),
+             EMBED_ERRTXT("Error retrieving content.\nUnable to"),
+             http_mthd, EMBED_ERRTXT("data to URI"), ctxt->uri );
+        xmlIOErr(XML_IO_WRITE, (const char *) msg);
+    }
+
+    else {
+
+    http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
+                    &content_type, content_encoding,
+                    content_lgth );
+
+    if ( http_ctxt != NULL ) {
+#ifdef DEBUG_HTTP
+        /*  If testing/debugging - dump reply with request content  */
+
+        FILE *  tst_file = NULL;
+        char    buffer[ 4096 ];
+        char *  dump_name = NULL;
+        int     avail;
+
+        xmlGenericError( xmlGenericErrorContext,
+            "xmlNanoHTTPCloseWrite:  HTTP %s to\n%s returned %d.\n",
+            http_mthd, ctxt->uri,
+            xmlNanoHTTPReturnCode( http_ctxt ) );
+
+        /*
+        **  Since either content or reply may be gzipped,
+        **  dump them to separate files instead of the
+        **  standard error context.
+        */
+
+        dump_name = tempnam( NULL, "lxml" );
+        if ( dump_name != NULL ) {
+        (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
+
+        tst_file = fopen( buffer, "wb" );
+        CHECK_ERRNO;
+
+        if ( tst_file != NULL ) {
+            xmlGenericError( xmlGenericErrorContext,
+            "Transmitted content saved in file:  %s\n", buffer );
+
+            fwrite( http_content, sizeof( char ),
+                    content_lgth, tst_file );
+            CHECK_ERRNO;
+            fclose( tst_file );
+        }
+
+        (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
+        tst_file = fopen( buffer, "wb" );
+        CHECK_ERRNO;
+
+        if ( tst_file != NULL ) {
+            xmlGenericError( xmlGenericErrorContext,
+            "Reply content saved in file:  %s\n", buffer );
+
+
+            while ( (avail = xmlNanoHTTPRead( http_ctxt,
+                    buffer, sizeof( buffer ) )) > 0 ) {
+
+            fwrite( buffer, sizeof( char ), avail, tst_file );
+            }
+
+            fclose( tst_file );
+        }
+
+        free( dump_name );
+        }
+#endif  /*  DEBUG_HTTP  */
+
+        http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
+        if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
+        close_rc = 0;
+        else {
+                xmlChar msg[500];
+                xmlStrPrintf(msg, 500,
+    (const xmlChar *) EMBED_ERRTXT("xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n"),
+                http_mthd, content_lgth,
+                EMBED_ERRTXT("bytes to URI"), ctxt->uri,
+                EMBED_ERRTXT("failed.  HTTP return code:"), http_rtn );
+        xmlIOErr(XML_IO_WRITE, (const char *) msg);
+            }
+
+        xmlNanoHTTPClose( http_ctxt );
+        xmlFree( content_type );
+    }
+    }
+
+    /*  Final cleanups  */
+
+    xmlFreeHTTPWriteCtxt( ctxt );
+
+    return ( close_rc );
+}
+
+/**
+ * xmlIOHTTPClosePut
+ *
+ * @param context The I/O context
+ *
+ * Close the transmit HTTP I/O channel and actually send data using a PUT
+ * HTTP method.
+ */
+static int
+xmlIOHTTPClosePut( void * ctxt )
+{
+    return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
+}
+
+
+/**
+ * xmlIOHTTPClosePost
+ *
+ * @param context The I/O context
+ *
+ * Close the transmit HTTP I/O channel and actually send data using a POST
+ * HTTP method.
+ */
+static int
+xmlIOHTTPClosePost( void * ctxt )
+{
+    return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+/************************************************************************
+ *                                  *
+ *          I/O for FTP file accesses           *
+ *                                  *
+ ************************************************************************/
+/**
+ * xmlIOFTPMatch:
+ * @param 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 (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
+    return(1);
+    return(0);
+}
+
+/**
+ * xmlIOFTPOpen:
+ * @param 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:
+ * @param context the I/O context
+ * @param buffer where to drop data
+ * @param 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:
+ * @param context the I/O context
+ *
+ * Close an FTP I/O channel
+ *
+ * Returns 0
+ */
+int
+xmlIOFTPClose (void * context)
+{
+    return ( xmlNanoFTPClose(context) );
+}
+#endif /* LIBXML_FTP_ENABLED */
+
+
+/**
+ * xmlRegisterInputCallbacks:
+ * @param matchFunc the xmlInputMatchCallback
+ * @param openFunc the xmlInputOpenCallback
+ * @param readFunc the xmlInputReadCallback
+ * @param closeFunc 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
+ *
+ * OOM: never
+ */
+XMLPUBFUNEXPORT int
+xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
+    xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
+    xmlInputCloseCallback closeFunc)
+{
+	LOAD_GS_DIRECT
+    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
+        return(-1);
+    }
+    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
+    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
+    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
+    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
+    xmlInputCallbackInitialized = 1;
+    return(xmlInputCallbackNr++);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlRegisterOutputCallbacks:
+ * @param matchFunc the xmlOutputMatchCallback
+ * @param openFunc the xmlOutputOpenCallback
+ * @param writeFunc the xmlOutputWriteCallback
+ * @param closeFunc the xmlOutputCloseCallback
+ *
+ * Register a new set of I/O callback for handling output.
+ *
+ * Returns the registered handler number or -1 in case of error
+ *
+ * OOM: never
+ */
+XMLPUBFUNEXPORT int
+xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
+    xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
+    xmlOutputCloseCallback closeFunc)
+{
+	LOAD_GS_DIRECT
+    if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
+        return(-1); 
+    }
+    
+    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
+    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
+    xmlOutputCallbackInitialized = 1;
+    return(xmlOutputCallbackNr++);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlRegisterDefaultInputCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ *
+ * OOM: never
+ */
+XMLPUBFUNEXPORT void
+xmlRegisterDefaultInputCallbacks(void)
+{
+	LOAD_GS_DIRECT
+    if (xmlInputCallbackInitialized){
+        
+        return;
+        }
+
+    xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
+                          xmlFileRead, xmlFileClose);
+#ifdef HAVE_ZLIB_H
+    xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
+                          xmlGzfileRead, xmlGzfileClose);
+#endif /* HAVE_ZLIB_H */
+
+    xmlInputCallbackInitialized = 1;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlRegisterDefaultOutputCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ *
+ * OOM: never (at least as far as initial size of table is enough)
+ */
+XMLPUBFUNEXPORT void
+xmlRegisterDefaultOutputCallbacks(void)
+{
+	LOAD_GS_DIRECT
+    if (xmlOutputCallbackInitialized)
+        return;
+
+    xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
+                               xmlFileWrite, xmlFileClose);
+
+#ifdef LIBXML_HTTP_ENABLED
+    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
+                         xmlIOHTTPWrite, xmlIOHTTPClosePut);
+#endif
+
+/*********************************
+ 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
+
+ Nor FTP PUT ....
+#ifdef LIBXML_FTP_ENABLED
+    xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
+                           xmlIOFTPWrite, xmlIOFTPClose);
+#endif
+ **********************************/
+    xmlOutputCallbackInitialized = 1;
+}
+
+#ifdef LIBXML_HTTP_ENABLED
+/**
+ * xmlRegisterHTTPPostCallbacks:
+ *
+ * By default, libxml submits HTTP output requests using the "PUT" method.
+ * Calling this method changes the HTTP output method to use the "POST"
+ * method instead.
+ *
+ */
+void
+xmlRegisterHTTPPostCallbacks( void )
+{
+    /*  Register defaults if not done previously  */
+
+    if ( xmlOutputCallbackInitialized == 0 )
+    xmlRegisterDefaultOutputCallbacks( );
+
+    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
+                           xmlIOHTTPWrite, xmlIOHTTPClosePost);
+    return;
+}
+#endif
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlAllocParserInputBuffer:
+ * @param enc the charset encoding if known
+ *
+ * Create a buffered parser input for progressive parsing
+ *
+ * Returns the new parser input or NULL
+ *
+ * OOM: possible --> NULL returned and OOM flag is set
+ */
+XMLPUBFUNEXPORT xmlParserInputBufferPtr
+xmlAllocParserInputBuffer(xmlCharEncoding enc)
+{
+	LOAD_GS_DIRECT
+    xmlParserInputBufferPtr ret;
+
+    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
+    if (!ret) {
+        xmlIOErrMemory(EMBED_ERRTXT("creating input buffer"));
+        return(NULL);
+    }
+    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
+    ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
+    if (!ret->buffer)
+        goto OOM;
+
+    
+    ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
+    ret->encoder = xmlGetCharEncodingHandler(enc);
+
+   if(OOM_FLAG)
+        goto OOM;
+
+    if (ret->encoder){
+        ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); // sets OOM flag
+        if(!ret->raw)
+            goto OOM;
+    }else{
+        ret->raw = NULL;
+    }
+    ret->readcallback = NULL;
+    ret->closecallback = NULL;
+    ret->context = NULL;
+    ret->compressed = -1;
+    ret->rawconsumed = 0;
+
+    return(ret);
+//-------------------
+OOM:
+    xmlFreeParserInputBuffer(ret);
+    return NULL;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlAllocOutputBuffer:
+ * @param encoder the encoding converter or NULL
+ *
+ * Create a buffered parser output
+ *
+ * Returns the new parser output or NULL
+ *
+ * OOM: possible --> NULL is returned && OOM flag is set
+ * 
+ */
+XMLPUBFUNEXPORT xmlOutputBufferPtr
+xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder)
+{
+    xmlOutputBufferPtr ret;
+
+    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
+    if (ret == NULL) {
+        xmlIOErrMemory(EMBED_ERRTXT("creating output buffer"));
+        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); // may set OOM flag
+    } //else {
+        //ret->conv = NULL; // unneeded -- it's NULL after memset() above
+    //}
+    ret->writecallback = NULL;
+    ret->closecallback = NULL;
+    ret->context = NULL;
+    ret->written = 0;
+
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlFreeParserInputBuffer:
+ * @param in a buffered parser input
+ *
+ * Free up the memory used by a buffered parser input
+ *
+ * OOM: never 
+ */
+XMLPUBFUNEXPORT void
+xmlFreeParserInputBuffer(xmlParserInputBufferPtr in)
+{
+    if (in == NULL) return;
+
+    if (in->raw) {
+        xmlBufferFree(in->raw);
+        in->raw = NULL;
+    }
+    if (in->encoder) {
+        xmlCharEncCloseFunc(in->encoder);
+    }
+    if (in->closecallback) {
+        in->closecallback(in->context);
+    }
+    if (in->buffer) {
+        xmlBufferFree(in->buffer);
+        in->buffer = NULL;
+    }
+
+    xmlFree(in);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlOutputBufferClose:
+ * @param 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.
+ */
+XMLPUBFUNEXPORT int
+xmlOutputBufferClose(xmlOutputBufferPtr out)
+{
+    int written;
+    int err_rc = 0;
+
+    if (!out)
+        return (-1);
+    if (out->writecallback != NULL)
+        xmlOutputBufferFlush(out);
+    if (out->closecallback != NULL) {
+        err_rc = 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;
+    }
+
+    if (out->error)
+        err_rc = -1;
+    xmlFree(out);
+    return ((err_rc == 0) ? written : err_rc);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlParserInputBufferCreateFilename:
+ * @param URI a C string containing the URI or filename
+ * @param 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
+ */
+XMLPUBFUNEXPORT xmlParserInputBufferPtr
+xmlParserInputBufferCreateFilename(const char* URI, xmlCharEncoding enc)
+{
+	LOAD_GS_DIRECT
+    xmlParserInputBufferPtr ret;
+    int     i = 0;
+    void*   context = NULL;
+
+    if (!URI)
+        return(NULL);
+
+    if (xmlInputCallbackInitialized == 0)
+        xmlRegisterDefaultInputCallbacks();
+
+    /*
+     * Try to find one of the input accept method accepting that scheme
+     * Go in reverse to give precedence to user defined handlers.
+     */
+    if (!context) {
+        for (i = xmlInputCallbackNr - 1;i >= 0;i--)
+            if (xmlInputCallbackTable[i].matchcallback &&
+                xmlInputCallbackTable[i].matchcallback(URI) != 0)
+            {
+                context = xmlInputCallbackTable[i].opencallback(URI);
+                if (context)
+                    break;
+            }
+    }
+    if (!context) {
+        return(NULL);
+    }
+
+    /*
+     * Allocate the Input buffer front-end.
+     */
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret)
+    {
+        ret->context = context;
+        ret->readcallback = xmlInputCallbackTable[i].readcallback;
+        ret->closecallback = xmlInputCallbackTable[i].closecallback;
+#ifdef HAVE_ZLIB_H
+        if (xmlInputCallbackTable[i].opencallback == xmlGzfileOpen &&
+            strcmp(URI, "-") != 0)
+        {
+            if (((z_stream *)context)->avail_in > 4)
+            {
+                char *cptr, buff4[4];
+
+                cptr = (char*) ((z_stream*)context)->next_in;
+                if (gzread(context, buff4, 4) == 4)
+                {
+                    if (strncmp(buff4, cptr, 4) == 0)
+                        ret->compressed = 0;
+                    else
+                        ret->compressed = 1;
+                    gzrewind(context);
+                }
+            }
+        }
+#endif
+    }
+    return(ret);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlOutputBufferCreateFilename:
+ * @param URI a C string containing the URI or filename
+ * @param encoder the encoding converter or NULL
+ * @param 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.
+ * currently if compression is set, the library only support
+ *       writing to a local file.
+ *
+ * Returns the new output or NULL
+ */
+XMLPUBFUNEXPORT xmlOutputBufferPtr
+xmlOutputBufferCreateFilename(const char *URI,
+                  xmlCharEncodingHandlerPtr encoder,
+                  int compression ATTRIBUTE_UNUSED)
+{
+	LOAD_GS_DIRECT
+    xmlOutputBufferPtr ret;
+    xmlURIPtr puri;
+    int i = 0;
+    void* context = NULL;
+    char* unescaped = NULL;
+#ifdef HAVE_ZLIB_H
+    int is_file_uri = 1; // Used only in ZLIB-enabled parts
+#endif
+
+    if (xmlOutputCallbackInitialized == 0)
+        xmlRegisterDefaultOutputCallbacks();
+    if (!URI)
+        return(NULL);
+
+    puri = xmlParseURI(URI);
+    if (!puri)
+        return NULL;
+#ifdef HAVE_ZLIB_H
+    if (puri->scheme &&
+        !xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file"))
+        is_file_uri = 0;
+#endif
+
+    /*
+    * try to limit the damages of the URI unescaping code.
+    */
+    if (puri->scheme)
+        {
+        unescaped = xmlURIUnescapeString(URI, 0, NULL);
+        
+        }
+    xmlFreeURI(puri);
+
+
+    /*
+     * Try to find one of the output accept method accepting that scheme
+     * Go in reverse to give precedence to user defined handlers.
+     * try with an unescaped version of the URI
+     */
+    if (unescaped) {
+#ifdef HAVE_ZLIB_H
+        if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
+            context = xmlGzfileOpenW(unescaped, compression);
+            if (context) {
+                ret = xmlAllocOutputBuffer(encoder);
+                if (ret) {
+                    ret->context = context;
+                    ret->writecallback = xmlGzfileWrite;
+                    ret->closecallback = xmlGzfileClose;
+                }
+                xmlFree(unescaped);
+                return(ret);
+            }
+        }
+#endif
+        for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
+            if (xmlOutputCallbackTable[i].matchcallback &&
+                xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)
+            {
+#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
+            /*  Need to pass compression parameter into HTTP open calls  */
+                if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
+                    context = xmlIOHTTPOpenW(unescaped, compression);
+                else
+#endif
+                    context = xmlOutputCallbackTable[i].opencallback(unescaped);
+                if (context)
+                    break;
+            }
+        }
+        xmlFree(unescaped);
+    } // end if(unescaped)
+
+    /*
+     * If this failed try with a non-escaped URI this may be a strange
+     * filename
+     */
+    if (!context) {
+#ifdef HAVE_ZLIB_H
+        if ((compression > 0) && (compression <= 9) && (is_file_uri == 1))
+        {
+            context = xmlGzfileOpenW(URI, compression);
+            if (context) {
+                ret = xmlAllocOutputBuffer(encoder);
+                if (ret) {
+                    ret->context = context;
+                    ret->writecallback = xmlGzfileWrite;
+                    ret->closecallback = xmlGzfileClose;
+                }
+                return(ret);
+            }
+        }
+#endif
+        for (i = xmlOutputCallbackNr - 1;i >= 0;i--)
+        {
+            if (xmlOutputCallbackTable[i].matchcallback  &&
+                xmlOutputCallbackTable[i].matchcallback(URI) != 0)
+            {
+#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
+                /*  Need to pass compression parameter into HTTP open calls  */
+                if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
+                    context = xmlIOHTTPOpenW(URI, compression);
+                else
+#endif
+                    context = xmlOutputCallbackTable[i].opencallback(URI);
+                if (context)
+                    break;
+            }
+        }
+    }
+
+    if (!context) {
+        return(NULL);
+    }
+
+    /*
+     * Allocate the Output buffer front-end.
+     */
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret) {
+        ret->context = context;
+        ret->writecallback = xmlOutputCallbackTable[i].writecallback;
+        ret->closecallback = xmlOutputCallbackTable[i].closecallback;
+    }
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#ifndef XMLENGINE_EXCLUDE_FILE_FUNC
+/**
+ * xmlParserInputBufferCreateFile:
+ * @param file a FILE*
+ * @param 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
+ */
+XMLPUBFUNEXPORT xmlParserInputBufferPtr
+xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc)
+{
+    xmlParserInputBufferPtr ret;
+
+    if (xmlInputCallbackInitialized == 0)
+        xmlRegisterDefaultInputCallbacks();
+
+    if (!file)
+        return(NULL);
+
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret) {
+        ret->context = file;
+        ret->readcallback = xmlFileRead;
+        ret->closecallback = xmlFileFlush;
+    }
+
+    return(ret);
+}
+#endif
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlOutputBufferCreateFile:
+ * @param file a FILE*
+ * @param 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 in OOM
+ * OOM: possible --> NULL is returned
+ */
+XMLPUBFUNEXPORT xmlOutputBufferPtr
+xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder)
+{
+	LOAD_GS_DIRECT
+    xmlOutputBufferPtr ret;
+
+    if (xmlOutputCallbackInitialized == 0)
+    xmlRegisterDefaultOutputCallbacks();
+
+    if (file == NULL) return(NULL);
+
+    ret = xmlAllocOutputBuffer(encoder);
+
+    if(ret){
+        ret->context = file;
+        ret->writecallback = xmlFileWrite;
+        ret->closecallback = xmlFileFlush;
+    }
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+
+/**
+ * xmlParserInputBufferCreateFd:
+ * @param fd a file descriptor number
+ * @param 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
+ */
+XMLPUBFUNEXPORT xmlParserInputBufferPtr
+xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc)
+{
+    xmlParserInputBufferPtr ret;
+
+    if (fd < 0) return(NULL);
+
+    ret = xmlAllocParserInputBuffer(enc);
+    if (ret != NULL) {
+        ret->context = (void *) (long) fd;
+    ret->readcallback = xmlFdRead;
+    ret->closecallback = xmlFdClose;
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferCreateMem:
+ * @param mem the memory input
+ * @param size the length of the memory block
+ * @param 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
+ *
+ * OOM: possible --> sets OOM flag, returns NULL for mem!=NULL && size>0
+ */
+XMLPUBFUNEXPORT xmlParserInputBufferPtr
+xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc)
+{
+	LOAD_GS_DIRECT
+    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);
+        if(OOM_FLAG){
+            xmlFreeParserInputBuffer(ret);
+            return NULL;
+        }
+    }
+
+    return(ret);
+}
+
+/**
+ * xmlParserInputBufferCreateStatic:
+ * @param mem the memory input
+ * @param size the length of the memory block
+ * @param enc the charset encoding if known
+ *
+ * Create a buffered parser input for the progressive parsing for the input
+ * from an immutable memory area. This will not copy the memory area to
+ * the buffer, but the memory is expected to be available until the end of
+ * the parsing, this is useful for example when using mmap'ed file.
+ *
+ * Returns the new parser input or NULL
+ */
+XMLPUBFUNEXPORT xmlParserInputBufferPtr
+xmlParserInputBufferCreateStatic(const char *mem, int size, xmlCharEncoding enc)
+{
+	LOAD_GS_DIRECT
+    xmlParserInputBufferPtr ret;
+
+    if (size <= 0) return(NULL);
+    if (mem == NULL) return(NULL);
+
+    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
+    if (ret == NULL) {
+    xmlIOErrMemory(EMBED_ERRTXT("creating input buffer"));
+    return(NULL);
+    }
+    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
+    ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size);
+    if (ret->buffer == NULL) {
+        xmlFree(ret);
+    return(NULL);
+    }
+    ret->encoder = xmlGetCharEncodingHandler(enc);
+    if (ret->encoder != NULL)
+        ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
+    else
+        ret->raw = NULL;
+    ret->compressed = -1;
+    ret->context = (void *) mem;
+    ret->readcallback = NULL;
+    ret->closecallback = NULL;
+
+    return(ret);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlOutputBufferCreateFd:
+ * @param fd a file descriptor number
+ * @param 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
+ */
+XMLPUBFUNEXPORT xmlOutputBufferPtr
+xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder)
+{
+    xmlOutputBufferPtr ret;
+
+    if (fd < 0) return(NULL);
+
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret != NULL) {
+        ret->context = (void *) (long) fd;
+    ret->writecallback = xmlFdWrite;
+    ret->closecallback = NULL;
+    }
+
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlParserInputBufferCreateIO:
+ * @param ioread an I/O read function
+ * @param ioclose an I/O close function
+ * @param ioctx an I/O handler
+ * @param 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
+ */
+XMLPUBFUNEXPORT 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);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlOutputBufferCreateIO:
+ * @param iowrite an I/O write function
+ * @param ioclose an I/O close function
+ * @param ioctx an I/O handler
+ * @param encoder 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
+ */
+XMLPUBFUNEXPORT 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);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlParserInputBufferPush:
+ * @param in a buffered parser input
+ * @param len the size in bytes of the array.
+ * @param buf an char array
+ *
+ * Push the content of the array 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.
+ *
+ * OOM: possible -->
+ */
+XMLPUBFUNEXPORT int
+xmlParserInputBufferPush(xmlParserInputBufferPtr in,
+                     int len, const char* buf)
+{
+    int nbchars; // initialization was unnecessary: = 0;
+
+    if (len < 0) return(0);
+
+    if (!in || in->error)
+        return(-1);
+
+    if (in->encoder)
+    {
+        unsigned int use;
+
+        /*
+         * Store the data in the incoming raw buffer
+         */
+        if (!in->raw) {
+            in->raw = xmlBufferCreate();
+        }
+        xmlBufferAdd(in->raw, (const xmlChar*) buf, len);
+
+        /*
+         * convert as much as possible to the parser reading buffer.
+         */
+        use = in->raw->use;
+        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
+        if (nbchars < 0) {
+            xmlIOErr(XML_IO_ENCODER, NULL);
+            in->error = XML_IO_ENCODER;
+            return(-1);
+        }
+        in->rawconsumed += (use - in->raw->use);
+    } 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);
+}
+
+/**
+ * endOfInput:
+ *
+ * When reading from an Input channel indicated end of file or error
+ * don't reread from it again.
+ */
+static int
+endOfInput (
+        void* context ATTRIBUTE_UNUSED,
+        char* buffer ATTRIBUTE_UNUSED,
+        int len ATTRIBUTE_UNUSED)
+{
+    return(0);
+}
+
+/**
+ * xmlParserInputBufferGrow:
+ * @param in a buffered parser input
+ * @param 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
+ *
+ * 
+ *       
+ *
+ * Returns the number of chars read and stored in the buffer, or -1
+ *         in case of error.
+ *
+ * OOM: possible --> sets OOM flag when returns 0
+ */
+XMLPUBFUNEXPORT int
+xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len)
+{
+	LOAD_GS_DIRECT
+    char *buffer = NULL;
+    int res = 0;
+    int nbchars = 0;
+    int buffree;
+    unsigned int needSize;
+
+    if ((in == NULL) || (in->error)) return(-1);
+    if ((len <= MINLEN) && (len != 4))
+        len = MINLEN;
+
+    buffree = in->buffer->size - in->buffer->use;
+    if (buffree <= 0) {
+        xmlIOErr(XML_IO_BUFFER_FULL, NULL);
+        in->error = XML_IO_BUFFER_FULL;
+        return(0);
+    }
+
+    needSize = in->buffer->use + len + 1;
+    if (needSize > in->buffer->size)
+    {
+        if (!xmlBufferResize(in->buffer, needSize))
+        {
+            xmlIOErrMemory(EMBED_ERRTXT("growing input buffer"));
+            in->error = XML_ERR_NO_MEMORY;
+            return(0);
+        }
+    }
+    buffer = (char*)&in->buffer->content[in->buffer->use];
+
+    /*
+     * Call the read method for this I/O type.
+     */
+    if (in->readcallback != NULL) {
+        
+        res = in->readcallback(in->context, &buffer[0], len);
+        if (res <= 0)
+            in->readcallback = endOfInput;
+    } else {
+        xmlIOErr(XML_IO_NO_INPUT, NULL);
+        in->error = XML_IO_NO_INPUT;
+        return(-1);
+    }
+    if (res < 0) {
+        return(-1);
+    }
+    len = res;
+    if (in->encoder != NULL) {
+        unsigned int use;
+
+        /*
+        * Store the data in the incoming raw buffer
+        */
+        if (in->raw == NULL) {
+            in->raw = xmlBufferCreate();
+            if(OOM_FLAG)
+                return 0;
+        }
+        xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
+        if(OOM_FLAG)
+            return 0;
+        /*
+        * convert as much as possible to the parser reading buffer.
+        */
+        use = in->raw->use;
+        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
+        if(OOM_FLAG)
+            return 0;
+
+        if (nbchars < 0) {
+            xmlIOErr(XML_IO_ENCODER, NULL);
+            in->error = XML_IO_ENCODER;
+            return(-1);
+        }
+        in->rawconsumed += (use - in->raw->use);
+    } else {
+        nbchars = len;
+        in->buffer->use += nbchars;
+        buffer[nbchars] = 0;
+    }
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext,
+        "I/O: read %d chars, buffer %d/%d\n",
+            nbchars, in->buffer->use, in->buffer->size);
+#endif
+    return(nbchars);
+}
+
+/**
+ * xmlParserInputBufferRead:
+ * @param in a buffered parser input
+ * @param 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.
+ */
+XMLPUBFUNEXPORT int
+xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len)
+{
+    if ((in == NULL) || (in->error)) return(-1);
+    if (in->readcallback != NULL)
+    return(xmlParserInputBufferGrow(in, len));
+    else if ((in->buffer != NULL) &&
+             (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE))
+    return(0);
+    else
+        return(-1);
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/**
+ * xmlOutputBufferWrite:
+ * @param out a buffered parser output
+ * @param len the size in bytes of the array.
+ * @param 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.
+ */
+XMLPUBFUNEXPORT 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 (!out || out->error)
+        return(-1);
+    if (len < 0)
+        return(0);
+    //if (out->error) return(-1);
+
+    do {
+    chunk = len;
+    if (chunk > 4 * MINLEN)
+        chunk = 4 * MINLEN;
+
+    /*
+     * first handle encoding stuff.
+     */
+    if (out->encoder) {
+        /*
+         * Store the data in the incoming raw buffer
+         */
+        if (!out->conv) {
+            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) && (ret != -3)) {
+            xmlIOErr(XML_IO_ENCODER, NULL);
+            out->error = XML_IO_ENCODER;
+            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, ret);
+        } else {
+            ret = out->writecallback(out->context,
+                 (const char *)out->buffer->content, nbchars);
+            if (ret >= 0)
+                xmlBufferShrink(out->buffer, ret);
+        }
+        if (ret < 0) {
+            xmlIOErr(XML_IO_WRITE, NULL);
+            out->error = XML_IO_WRITE;
+            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);
+}
+
+/**
+ * xmlEscapeContent:
+ * @param out a pointer to an array of bytes to store the result
+ * @param outlen the length of out
+ * @param in a pointer to an array of unescaped UTF-8 bytes
+ * @param inlen the length of in
+ *
+ * Take a block of UTF-8 chars in and escape them.
+ * Returns 0 if success, or -1 otherwise
+ * The value of inlen after return is the number of octets consumed
+ *     if the return value is positive, else unpredictable.
+ * The value of outlen after return is the number of octets consumed.
+ */
+static int
+xmlEscapeContent(unsigned char* out, int *outlen, const xmlChar* in, int *inlen)
+{
+    unsigned char* outstart = out;
+    const unsigned char* base = in;
+    unsigned char* outend = out + *outlen;
+    const unsigned char* inend;
+
+    inend = in + (*inlen);
+
+    while ((in < inend) && (out < outend))
+    {
+        if (*in == '<') {
+            if (outend - out < 4) break;
+            *out++ = '&';
+            *out++ = 'l';
+            *out++ = 't';
+            *out++ = ';';
+        } else if (*in == '>') {
+            if (outend - out < 4) break;
+            *out++ = '&';
+            *out++ = 'g';
+            *out++ = 't';
+            *out++ = ';';
+        } else if (*in == '&') {
+            if (outend - out < 5) break;
+            *out++ = '&';
+            *out++ = 'a';
+            *out++ = 'm';
+            *out++ = 'p';
+            *out++ = ';';
+        } else if (*in == '\r') {
+            if (outend - out < 5) break;
+            *out++ = '&';
+            *out++ = '#';
+            *out++ = '1';
+            *out++ = '3';
+            *out++ = ';';
+        } else {
+            *out++ = (unsigned char) *in;
+        }
+        ++in;
+    }
+    *outlen = out - outstart;
+    *inlen = in - base;
+    return(0);
+}
+
+/**
+ * xmlOutputBufferWriteEscape:
+ * @param out a buffered parser output
+ * @param str a zero terminated UTF-8 string
+ * @param escaping an optional escaping function (or NULL)
+ *
+ * Write the content of the string in the output I/O buffer
+ * This routine escapes the caracters and then 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.
+ */
+XMLPUBFUNEXPORT int
+xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
+                           xmlCharEncodingOutputFunc escaping)
+{
+    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 currently processed from str */
+    int len;         /* number of bytes in str */
+    int cons;        /* byte from str consumed */
+
+    if (!out || out->error || !str)
+        return(-1);
+    len = strlen((const char*)str);
+    if (len < 0)
+        return(0);
+    if (out->error)
+        return(-1);
+    if (!escaping)
+        escaping = xmlEscapeContent;
+
+    do {
+        /*
+     * how many bytes to consume and how many bytes to store.
+     */
+    cons = len;
+    chunk = (out->buffer->size - out->buffer->use) - 1;
+
+    /*
+     * first handle encoding stuff.
+     */
+    if (out->encoder != NULL) {
+        /*
+         * Store the data in the incoming raw buffer
+         */
+        if (out->conv == NULL) {
+        out->conv = xmlBufferCreate();
+        }
+        ret = escaping(out->buffer->content + out->buffer->use ,
+                       &chunk, str, &cons);
+        if (ret < 0)
+            return(-1);
+        out->buffer->use += chunk;
+        out->buffer->content[out->buffer->use] = 0;
+
+        if ((out->buffer->use < MINLEN) && (cons == len))
+        goto done;
+
+        /*
+         * convert as much as possible to the output buffer.
+         */
+        ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+        if ((ret < 0) && (ret != -3)) {
+        xmlIOErr(XML_IO_ENCODER, NULL);
+        out->error = XML_IO_ENCODER;
+        return(-1);
+        }
+        nbchars = out->conv->use;
+    } else {
+        ret = escaping(out->buffer->content + out->buffer->use ,
+                       &chunk, str, &cons);
+        if (ret < 0)
+            return(-1);
+        out->buffer->use += chunk;
+        out->buffer->content[out->buffer->use] = 0;
+        nbchars = out->buffer->use;
+    }
+    str += cons;
+    len -= cons;
+
+    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, ret);
+        } else {
+        ret = out->writecallback(out->context,
+                 (const char *)out->buffer->content, nbchars);
+        if (ret >= 0)
+            xmlBufferShrink(out->buffer, ret);
+        }
+        if (ret < 0) {
+        xmlIOErr(XML_IO_WRITE, NULL);
+        out->error = XML_IO_WRITE;
+        return(ret);
+        }
+        out->written += ret;
+    } else if (out->buffer->size - out->buffer->use < MINLEN) {
+        if (!xmlBufferResize(out->buffer, out->buffer->size + MINLEN))
+        {
+            chunk = out->buffer->size - out->buffer->use - 1;
+            if(chunk <= 0)               
+            {
+               /* can't proceed without more buffer */
+                out->error = XML_ERR_NO_MEMORY;
+                return(-1);
+            }
+
+        }
+    }
+    written += nbchars;
+    } while (len > 0);
+
+done:
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext, "I/O: wrote %d chars\n", written);
+#endif
+    return(written);
+}
+
+/**
+ * xmlOutputBufferWriteString:
+ * @param out a buffered parser output
+ * @param 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.
+ *
+ * OOM: possible
+ */
+XMLPUBFUNEXPORT int
+xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str)
+{
+    int len;
+
+    if (!out || out->error || !str)
+        return(-1);
+    len = strlen(str);
+
+    if (len > 0)
+        return(xmlOutputBufferWrite(out, len, str));
+    return(len);
+}
+
+/**
+ * xmlOutputBufferFlush:
+ * @param out a buffered output
+ *
+ * flushes the output I/O channel
+ *
+ * Returns the number of byte written or -1 in case of error.
+ */
+XMLPUBFUNEXPORT int
+xmlOutputBufferFlush(xmlOutputBufferPtr out)
+{
+    int ret = 0;
+
+    if (!out || out->error)
+        return(-1);
+
+// XMLENGINE: Replaced code
+/*
+    if (out->conv && out->encoder)
+    {
+        int nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+        if (nbchars < 0) {
+            xmlIOErr(XML_IO_ENCODER, NULL);
+            out->error = XML_IO_ENCODER;
+            return(-1);
+        }
+    }
+
+    if (out->conv) &&
+        out->encoder &&
+        out->writecallback)
+    {
+        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 (out->writecallback)
+    {
+        xmlBufferPtr buffer;
+
+        /*
+        * first handle encoding stuff.
+        */
+        if (out->conv && out->encoder)
+        {
+            /*
+            * convert as much as possible to the parser reading buffer.
+            */
+            int nbchars;
+
+            buffer = out->conv;
+            nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+            if (nbchars < 0) {
+                xmlIOErr(XML_IO_ENCODER, NULL);
+                out->error = XML_IO_ENCODER;
+                return(-1);
+            }
+        } else {
+            buffer = out->buffer;
+        }
+
+        /*
+        * second flush the stuff to the I/O channel
+        */
+        ret = out->writecallback(
+                        out->context,
+                        (const char*) buffer->content,
+                        buffer->use);
+        if (ret >= 0)
+            xmlBufferShrink(buffer, ret);
+    }
+    if (ret < 0) {
+        xmlIOErr(XML_IO_FLUSH, NULL);
+        out->error = XML_IO_FLUSH;
+        return(ret);
+    }
+    out->written += ret;
+
+#ifdef DEBUG_INPUT
+    xmlGenericError(xmlGenericErrorContext, "I/O: flushed %d chars\n", ret);
+#endif
+    return(ret);
+}
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+/**
+ * xmlParserGetDirectory:
+ * @param filename the path to a file
+ *
+ * lookup the directory for that file
+ *
+ * Returns a new allocated string containing the directory, or NULL.
+ */
+XMLPUBFUNEXPORT char*
+xmlParserGetDirectory(const char* filename)
+{
+	LOAD_GS_DIRECT
+    char* ret = NULL;
+    char  dir[1024]; 
+    char* cur;
+    char  sep;
+
+    if (!filename)
+        return(NULL);
+
+    if (xmlInputCallbackInitialized == 0)
+        xmlRegisterDefaultInputCallbacks();
+
+
+    sep = '\\';  // NOTE: All backslashes are converted to slashes
+               //       when converting all local paths to URIs;
+               //       Later they are converted to backslashes..
+               // Seems inefficient, but works for now...
+
+    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)) {
+            dir[1023] = 0;
+            ret = xmlMemStrdup(dir);
+        }
+    }
+    return(ret);
+}
+
+/****************************************************************
+ *                                                              *
+ *      External entities loading                               *
+ *                                                              *
+ ****************************************************************/
+
+/**
+ * xmlCheckHTTPInput:
+ * @param ctxt an XML parser context
+ * @param ret an XML parser input
+ *
+ * Check an input in case it was created from an HTTP stream, in that
+ * case it will handle encoding and update of the base URL in case of
+ * redirection. It also checks for HTTP errors in which case the input
+ * is cleanly freed up and an appropriate error is raised in context
+ *
+ * Returns the input or NULL in case of HTTP error.
+ */
+XMLPUBFUNEXPORT xmlParserInputPtr
+xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret)
+{
+#ifdef LIBXML_HTTP_ENABLED
+    if ((ret != NULL) && (ret->buf != NULL) &&
+        (ret->buf->readcallback == xmlIOHTTPRead) &&
+        (ret->buf->context != NULL)) {
+        const char *encoding;
+        const char *redir;
+        const char *mime;
+        int code;
+
+        code = xmlNanoHTTPReturnCode(ret->buf->context);
+        if (code >= 400) {
+            /* fatal error */
+        if (ret->filename != NULL)
+        __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
+                         (const char *) ret->filename);
+        else
+        __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
+            xmlFreeInputStream(ret);
+            ret = NULL;
+        } else {
+
+            mime = xmlNanoHTTPMimeType(ret->buf->context);
+            if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
+                (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
+                encoding = xmlNanoHTTPEncoding(ret->buf->context);
+                if (encoding != NULL) {
+                    xmlCharEncodingHandlerPtr handler;
+
+                    handler = xmlFindCharEncodingHandler(encoding);
+                    if (handler != NULL) {
+                        xmlSwitchInputEncoding(ctxt, ret, handler);
+                    } else {
+                        __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
+                                         "Unknown encoding %s",
+                                         BAD_CAST encoding, NULL);
+                    }
+                    if (ret->encoding == NULL)
+                        ret->encoding = xmlStrdup(BAD_CAST encoding);
+                }
+#if 0
+            } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
+#endif
+            }
+            redir = xmlNanoHTTPRedir(ret->buf->context);
+            if (redir != NULL) {
+                if (ret->filename != NULL)
+                    xmlFree((xmlChar *) ret->filename);
+                if (ret->directory != NULL) {
+                    xmlFree((xmlChar *) ret->directory);
+                    ret->directory = NULL;
+                }
+                ret->filename =
+                    (char *) xmlStrdup((const xmlChar *) redir);
+            }
+        }
+    }
+#endif
+    return(ret);
+}
+
+
+static int xmlSysIDExists(const char* URL)
+{
+#ifdef HAVE_STAT
+    int ret;
+    struct stat info;
+    const char *path;
+
+    if (URL == NULL)
+    return(0);
+
+    if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
+    path = &URL[17];
+    else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
+    path = &URL[8];
+    } else {
+        path = URL;
+    }
+
+    ret = stat(path, &info);
+    if (ret == 0)
+        return(1);
+#endif
+    return(0);
+}
+
+/**
+ * xmlDefaultExternalEntityLoader:
+ * @param URL the URL for the entity to load
+ * @param ID the System ID for the entity to load
+ * @param 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.
+ */
+xmlParserInputPtr
+xmlDefaultExternalEntityLoader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt)
+{
+    xmlParserInputPtr ret = NULL;
+    xmlChar *resource = NULL;
+
+#ifdef LIBXML_CATALOG_ENABLED
+    xmlCatalogAllow pref;
+#endif
+
+#ifdef DEBUG_EXTERNAL_ENTITIES
+    xmlGenericError(xmlGenericErrorContext,
+                    "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
+#endif
+#ifdef LIBXML_CATALOG_ENABLED
+    if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
+        int options = ctxt->options;
+
+    ctxt->options -= XML_PARSE_NONET;
+        ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+    ctxt->options = options;
+    return(ret);
+    }
+
+    /*
+     * If the resource doesn't exists as a file,
+     * try to load it from the resource pointed in the catalogs
+     */
+    pref = xmlCatalogGetDefaults();
+
+    if ((pref != XML_CATA_ALLOW_NONE) && (!xmlSysIDExists(URL))) {
+        /*
+         * Do a local lookup
+         */
+        if ((ctxt->catalogs != NULL) &&
+            ((pref == XML_CATA_ALLOW_ALL) ||
+             (pref == XML_CATA_ALLOW_DOCUMENT))) {
+            resource = xmlCatalogLocalResolve(ctxt->catalogs,
+                                              (const xmlChar *) ID,
+                                              (const xmlChar *) URL);
+        }
+        /*
+         * Try a global lookup
+         */
+        if ((resource == NULL) &&
+            ((pref == XML_CATA_ALLOW_ALL) ||
+             (pref == XML_CATA_ALLOW_GLOBAL))) {
+            resource = xmlCatalogResolve((const xmlChar *) ID,
+                                         (const xmlChar *) URL);
+        }
+        if ((resource == NULL) && (URL != NULL))
+            resource = xmlStrdup((const xmlChar *) URL);
+
+        /*
+         * 
+         */
+        if ((resource != NULL)
+            && (!xmlSysIDExists((const char *) resource))) {
+            xmlChar *tmp = NULL;
+
+            if ((ctxt->catalogs != NULL) &&
+                ((pref == XML_CATA_ALLOW_ALL) ||
+                 (pref == XML_CATA_ALLOW_DOCUMENT))) {
+                tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
+            }
+            if ((tmp == NULL) &&
+                ((pref == XML_CATA_ALLOW_ALL) ||
+                 (pref == XML_CATA_ALLOW_GLOBAL))) {
+                tmp = xmlCatalogResolveURI(resource);
+            }
+
+            if (tmp) {
+                xmlFree(resource);
+                resource = tmp;
+            }
+        }
+    }
+#endif
+
+    if (!resource)
+        resource = (xmlChar*) URL;
+
+    if (!resource) {
+        if (!ID)
+            ID = "NULL";
+        __xmlLoaderErr(ctxt, EMBED_ERRTXT("failed to load external entity \"%s\"\n"), ID);
+        return (NULL);
+    }
+    ret = xmlNewInputFromFile(ctxt, (const char*) resource);
+    if (resource  &&  resource != (xmlChar*)URL) 
+        xmlFree(resource);
+    return (ret);
+}
+
+#ifndef XMLENGINE_EXCLUDE_UNUSED
+/**
+ * xmlSetExternalEntityLoader:
+ * @param 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);
+}
+#endif /* ifndef XMLENGINE_EXCLUDE_UNUSED */
+
+/**
+ * xmlLoadExternalEntity:
+ * @param URL the URL for the entity to load
+ * @param ID the Public ID for the entity to load
+ * @param 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
+ * 
+ *
+ * Returns the xmlParserInputPtr or NULL
+ *
+ * OOM:
+ */
+XMLPUBFUNEXPORT xmlParserInputPtr
+xmlLoadExternalEntity(const char *URL, const char *ID, xmlParserCtxtPtr ctxt)
+{
+	LOAD_GS_DIRECT
+    if (URL && (xmlSysIDExists(URL) == 0)) {
+        char* canonicFilename;
+        xmlParserInputPtr ret;
+
+        canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
+        if (!canonicFilename) {
+            xmlIOErrMemory(EMBED_ERRTXT("building canonical path\n"));
+            return(NULL);
+        }
+
+        ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
+        xmlFree(canonicFilename);
+        return(ret);
+    }
+    return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
+}
+
+/************************************************************************
+ *                                                                      *
+ *      Disabling Network access                                        *
+ *                                                                      *
+ ************************************************************************/
+
+#ifdef LIBXML_CATALOG_ENABLED
+static int
+xmlNoNetExists(const char *URL)
+{
+#ifdef HAVE_STAT
+    int ret;
+    struct stat info;
+    const char *path;
+
+    if (!URL)
+        return (0);
+
+    if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
+    path = &URL[17];
+    else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
+        path = &URL[8];
+    } else
+        path = URL;
+    ret = stat(path, &info);
+    if (ret == 0)
+        return (1);
+#endif
+    return (0);
+}
+#endif
+
+/**
+ * xmlNoNetExternalEntityLoader:
+ * @param URL the URL for the entity to load
+ * @param ID the System ID for the entity to load
+ * @param ctxt the context in which the entity is called or NULL
+ *
+ * A specific entity loader disabling network accesses, though still
+ * allowing local catalog accesses for resolution.
+ *
+ * Returns a new allocated xmlParserInputPtr, or NULL.
+ */
+XMLPUBFUNEXPORT xmlParserInputPtr
+xmlNoNetExternalEntityLoader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt)
+{
+    xmlParserInputPtr input = NULL;
+    xmlChar *resource = NULL;
+
+#ifdef LIBXML_CATALOG_ENABLED
+    xmlCatalogAllow pref;
+
+    /*
+     * If the resource doesn't exists as a file,
+     * try to load it from the resource pointed in the catalogs
+     */
+    pref = xmlCatalogGetDefaults();
+
+    if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
+    /*
+     * Do a local lookup
+     */
+    if ((ctxt->catalogs != NULL) &&
+        ((pref == XML_CATA_ALLOW_ALL) ||
+         (pref == XML_CATA_ALLOW_DOCUMENT))) {
+        resource = xmlCatalogLocalResolve(ctxt->catalogs,
+                          (const xmlChar *)ID,
+                          (const xmlChar *)URL);
+        }
+    /*
+     * Try a global lookup
+     */
+    if ((resource == NULL) &&
+        ((pref == XML_CATA_ALLOW_ALL) ||
+         (pref == XML_CATA_ALLOW_GLOBAL))) {
+        resource = xmlCatalogResolve((const xmlChar *)ID,
+                     (const xmlChar *)URL);
+    }
+    if ((resource == NULL) && (URL != NULL))
+        resource = xmlStrdup((const xmlChar *) URL);
+
+    /*
+     * 
+     */
+    if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
+        xmlChar *tmp = NULL;
+
+        if ((ctxt->catalogs != NULL) &&
+        ((pref == XML_CATA_ALLOW_ALL) ||
+         (pref == XML_CATA_ALLOW_DOCUMENT))) {
+        tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
+        }
+        if ((tmp == NULL) &&
+        ((pref == XML_CATA_ALLOW_ALL) ||
+             (pref == XML_CATA_ALLOW_GLOBAL))) {
+        tmp = xmlCatalogResolveURI(resource);
+        }
+
+        if (tmp != NULL) {
+        xmlFree(resource);
+        resource = tmp;
+        }
+    }
+    }
+#endif
+    if (resource == NULL)
+    resource = (xmlChar *) URL;
+
+    if (resource != NULL) {
+        if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
+            (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
+            xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
+        if (resource != (xmlChar *) URL)
+        xmlFree(resource);
+        return(NULL);
+    }
+    }
+    input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
+    if (resource != (xmlChar *) URL)
+    xmlFree(resource);
+    return(input);
+}
+