Blame xmlIO.c

Packit 423ecb
/*
Packit 423ecb
 * xmlIO.c : implementation of the I/O interfaces used by the parser
Packit 423ecb
 *
Packit 423ecb
 * See Copyright for the status of this software.
Packit 423ecb
 *
Packit 423ecb
 * daniel@veillard.com
Packit 423ecb
 *
Packit 423ecb
 * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
#define IN_LIBXML
Packit 423ecb
#include "libxml.h"
Packit 423ecb
Packit 423ecb
#include <string.h>
Packit 423ecb
#include <stddef.h>
Packit 423ecb
#ifdef HAVE_ERRNO_H
Packit 423ecb
#include <errno.h>
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
Packit 423ecb
#ifdef HAVE_SYS_TYPES_H
Packit 423ecb
#include <sys/types.h>
Packit 423ecb
#endif
Packit 423ecb
#ifdef HAVE_SYS_STAT_H
Packit 423ecb
#include <sys/stat.h>
Packit 423ecb
#endif
Packit 423ecb
#ifdef HAVE_FCNTL_H
Packit 423ecb
#include <fcntl.h>
Packit 423ecb
#endif
Packit 423ecb
#ifdef HAVE_UNISTD_H
Packit 423ecb
#include <unistd.h>
Packit 423ecb
#endif
Packit 423ecb
#ifdef HAVE_STDLIB_H
Packit 423ecb
#include <stdlib.h>
Packit 423ecb
#endif
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
#include <zlib.h>
Packit 423ecb
#endif
Packit 423ecb
#ifdef HAVE_LZMA_H
Packit 423ecb
#include <lzma.h>
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit 423ecb
#define WIN32_LEAN_AND_MEAN
Packit 423ecb
#include <windows.h>
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
#if defined(_WIN32_WCE)
Packit 423ecb
#include <winnls.h> /* for CP_UTF8 */
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
#ifndef S_ISDIR
Packit 423ecb
#  ifdef _S_ISDIR
Packit 423ecb
#    define S_ISDIR(x) _S_ISDIR(x)
Packit 423ecb
#  elif defined(S_IFDIR)
Packit 423ecb
#    ifdef S_IFMT
Packit 423ecb
#      define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
Packit 423ecb
#    elif defined(_S_IFMT)
Packit 423ecb
#      define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
Packit 423ecb
#    endif
Packit 423ecb
#  endif
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
#include <libxml/xmlmemory.h>
Packit 423ecb
#include <libxml/parser.h>
Packit 423ecb
#include <libxml/parserInternals.h>
Packit 423ecb
#include <libxml/xmlIO.h>
Packit 423ecb
#include <libxml/uri.h>
Packit 423ecb
#include <libxml/nanohttp.h>
Packit 423ecb
#include <libxml/nanoftp.h>
Packit 423ecb
#include <libxml/xmlerror.h>
Packit 423ecb
#ifdef LIBXML_CATALOG_ENABLED
Packit 423ecb
#include <libxml/catalog.h>
Packit 423ecb
#endif
Packit 423ecb
#include <libxml/globals.h>
Packit 423ecb
Packit 423ecb
#include "buf.h"
Packit 423ecb
#include "enc.h"
Packit 423ecb
Packit 423ecb
/* #define VERBOSE_FAILURE */
Packit 423ecb
/* #define DEBUG_EXTERNAL_ENTITIES */
Packit 423ecb
/* #define DEBUG_INPUT */
Packit 423ecb
Packit 423ecb
#ifdef DEBUG_INPUT
Packit 423ecb
#define MINLEN 40
Packit 423ecb
#else
Packit 423ecb
#define MINLEN 4000
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * Input I/O callback sets
Packit 423ecb
 */
Packit 423ecb
typedef struct _xmlInputCallback {
Packit 423ecb
    xmlInputMatchCallback matchcallback;
Packit 423ecb
    xmlInputOpenCallback opencallback;
Packit 423ecb
    xmlInputReadCallback readcallback;
Packit 423ecb
    xmlInputCloseCallback closecallback;
Packit 423ecb
} xmlInputCallback;
Packit 423ecb
Packit 423ecb
#define MAX_INPUT_CALLBACK 15
Packit 423ecb
Packit 423ecb
static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
Packit 423ecb
static int xmlInputCallbackNr = 0;
Packit 423ecb
static int xmlInputCallbackInitialized = 0;
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/*
Packit 423ecb
 * Output I/O callback sets
Packit 423ecb
 */
Packit 423ecb
typedef struct _xmlOutputCallback {
Packit 423ecb
    xmlOutputMatchCallback matchcallback;
Packit 423ecb
    xmlOutputOpenCallback opencallback;
Packit 423ecb
    xmlOutputWriteCallback writecallback;
Packit 423ecb
    xmlOutputCloseCallback closecallback;
Packit 423ecb
} xmlOutputCallback;
Packit 423ecb
Packit 423ecb
#define MAX_OUTPUT_CALLBACK 15
Packit 423ecb
Packit 423ecb
static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
Packit 423ecb
static int xmlOutputCallbackNr = 0;
Packit 423ecb
static int xmlOutputCallbackInitialized = 0;
Packit 423ecb
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Tree memory error handler				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
static const char *IOerr[] = {
Packit 423ecb
    "Unknown IO error",         /* UNKNOWN */
Packit 423ecb
    "Permission denied",	/* EACCES */
Packit 423ecb
    "Resource temporarily unavailable",/* EAGAIN */
Packit 423ecb
    "Bad file descriptor",	/* EBADF */
Packit 423ecb
    "Bad message",		/* EBADMSG */
Packit 423ecb
    "Resource busy",		/* EBUSY */
Packit 423ecb
    "Operation canceled",	/* ECANCELED */
Packit 423ecb
    "No child processes",	/* ECHILD */
Packit 423ecb
    "Resource deadlock avoided",/* EDEADLK */
Packit 423ecb
    "Domain error",		/* EDOM */
Packit 423ecb
    "File exists",		/* EEXIST */
Packit 423ecb
    "Bad address",		/* EFAULT */
Packit 423ecb
    "File too large",		/* EFBIG */
Packit 423ecb
    "Operation in progress",	/* EINPROGRESS */
Packit 423ecb
    "Interrupted function call",/* EINTR */
Packit 423ecb
    "Invalid argument",		/* EINVAL */
Packit 423ecb
    "Input/output error",	/* EIO */
Packit 423ecb
    "Is a directory",		/* EISDIR */
Packit 423ecb
    "Too many open files",	/* EMFILE */
Packit 423ecb
    "Too many links",		/* EMLINK */
Packit 423ecb
    "Inappropriate message buffer length",/* EMSGSIZE */
Packit 423ecb
    "Filename too long",	/* ENAMETOOLONG */
Packit 423ecb
    "Too many open files in system",/* ENFILE */
Packit 423ecb
    "No such device",		/* ENODEV */
Packit 423ecb
    "No such file or directory",/* ENOENT */
Packit 423ecb
    "Exec format error",	/* ENOEXEC */
Packit 423ecb
    "No locks available",	/* ENOLCK */
Packit 423ecb
    "Not enough space",		/* ENOMEM */
Packit 423ecb
    "No space left on device",	/* ENOSPC */
Packit 423ecb
    "Function not implemented",	/* ENOSYS */
Packit 423ecb
    "Not a directory",		/* ENOTDIR */
Packit 423ecb
    "Directory not empty",	/* ENOTEMPTY */
Packit 423ecb
    "Not supported",		/* ENOTSUP */
Packit 423ecb
    "Inappropriate I/O control operation",/* ENOTTY */
Packit 423ecb
    "No such device or address",/* ENXIO */
Packit 423ecb
    "Operation not permitted",	/* EPERM */
Packit 423ecb
    "Broken pipe",		/* EPIPE */
Packit 423ecb
    "Result too large",		/* ERANGE */
Packit 423ecb
    "Read-only file system",	/* EROFS */
Packit 423ecb
    "Invalid seek",		/* ESPIPE */
Packit 423ecb
    "No such process",		/* ESRCH */
Packit 423ecb
    "Operation timed out",	/* ETIMEDOUT */
Packit 423ecb
    "Improper link",		/* EXDEV */
Packit 423ecb
    "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
Packit 423ecb
    "encoder error",		/* XML_IO_ENCODER */
Packit 423ecb
    "flush error",
Packit 423ecb
    "write error",
Packit 423ecb
    "no input",
Packit 423ecb
    "buffer full",
Packit 423ecb
    "loading error",
Packit 423ecb
    "not a socket",		/* ENOTSOCK */
Packit 423ecb
    "already connected",	/* EISCONN */
Packit 423ecb
    "connection refused",	/* ECONNREFUSED */
Packit 423ecb
    "unreachable network",	/* ENETUNREACH */
Packit 423ecb
    "adddress in use",		/* EADDRINUSE */
Packit 423ecb
    "already in use",		/* EALREADY */
Packit 423ecb
    "unknown address familly",	/* EAFNOSUPPORT */
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
/**
Packit 423ecb
 * __xmlIOWin32UTF8ToWChar:
Packit 423ecb
 * @u8String:  uft-8 string
Packit 423ecb
 *
Packit 423ecb
 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
Packit 423ecb
 */
Packit 423ecb
static wchar_t *
Packit 423ecb
__xmlIOWin32UTF8ToWChar(const char *u8String)
Packit 423ecb
{
Packit 423ecb
    wchar_t *wString = NULL;
Packit 423ecb
Packit 423ecb
    if (u8String) {
Packit 423ecb
        int wLen =
Packit 423ecb
            MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
Packit 423ecb
                                -1, NULL, 0);
Packit 423ecb
        if (wLen) {
Packit 423ecb
            wString = xmlMalloc(wLen * sizeof(wchar_t));
Packit 423ecb
            if (wString) {
Packit 423ecb
                if (MultiByteToWideChar
Packit 423ecb
                    (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
Packit 423ecb
                    xmlFree(wString);
Packit 423ecb
                    wString = NULL;
Packit 423ecb
                }
Packit 423ecb
            }
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return wString;
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOErrMemory:
Packit 423ecb
 * @extra:  extra informations
Packit 423ecb
 *
Packit 423ecb
 * Handle an out of memory condition
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
xmlIOErrMemory(const char *extra)
Packit 423ecb
{
Packit 423ecb
    __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * __xmlIOErr:
Packit 423ecb
 * @code:  the error number
Packit 423ecb
 * @
Packit 423ecb
 * @extra:  extra informations
Packit 423ecb
 *
Packit 423ecb
 * Handle an I/O error
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
__xmlIOErr(int domain, int code, const char *extra)
Packit 423ecb
{
Packit 423ecb
    unsigned int idx;
Packit 423ecb
Packit 423ecb
    if (code == 0) {
Packit 423ecb
#ifdef HAVE_ERRNO_H
Packit 423ecb
	if (errno == 0) code = 0;
Packit 423ecb
#ifdef EACCES
Packit 423ecb
        else if (errno == EACCES) code = XML_IO_EACCES;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EAGAIN
Packit 423ecb
        else if (errno == EAGAIN) code = XML_IO_EAGAIN;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EBADF
Packit 423ecb
        else if (errno == EBADF) code = XML_IO_EBADF;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EBADMSG
Packit 423ecb
        else if (errno == EBADMSG) code = XML_IO_EBADMSG;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EBUSY
Packit 423ecb
        else if (errno == EBUSY) code = XML_IO_EBUSY;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ECANCELED
Packit 423ecb
        else if (errno == ECANCELED) code = XML_IO_ECANCELED;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ECHILD
Packit 423ecb
        else if (errno == ECHILD) code = XML_IO_ECHILD;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EDEADLK
Packit 423ecb
        else if (errno == EDEADLK) code = XML_IO_EDEADLK;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EDOM
Packit 423ecb
        else if (errno == EDOM) code = XML_IO_EDOM;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EEXIST
Packit 423ecb
        else if (errno == EEXIST) code = XML_IO_EEXIST;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EFAULT
Packit 423ecb
        else if (errno == EFAULT) code = XML_IO_EFAULT;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EFBIG
Packit 423ecb
        else if (errno == EFBIG) code = XML_IO_EFBIG;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EINPROGRESS
Packit 423ecb
        else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EINTR
Packit 423ecb
        else if (errno == EINTR) code = XML_IO_EINTR;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EINVAL
Packit 423ecb
        else if (errno == EINVAL) code = XML_IO_EINVAL;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EIO
Packit 423ecb
        else if (errno == EIO) code = XML_IO_EIO;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EISDIR
Packit 423ecb
        else if (errno == EISDIR) code = XML_IO_EISDIR;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EMFILE
Packit 423ecb
        else if (errno == EMFILE) code = XML_IO_EMFILE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EMLINK
Packit 423ecb
        else if (errno == EMLINK) code = XML_IO_EMLINK;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EMSGSIZE
Packit 423ecb
        else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENAMETOOLONG
Packit 423ecb
        else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENFILE
Packit 423ecb
        else if (errno == ENFILE) code = XML_IO_ENFILE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENODEV
Packit 423ecb
        else if (errno == ENODEV) code = XML_IO_ENODEV;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOENT
Packit 423ecb
        else if (errno == ENOENT) code = XML_IO_ENOENT;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOEXEC
Packit 423ecb
        else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOLCK
Packit 423ecb
        else if (errno == ENOLCK) code = XML_IO_ENOLCK;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOMEM
Packit 423ecb
        else if (errno == ENOMEM) code = XML_IO_ENOMEM;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOSPC
Packit 423ecb
        else if (errno == ENOSPC) code = XML_IO_ENOSPC;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOSYS
Packit 423ecb
        else if (errno == ENOSYS) code = XML_IO_ENOSYS;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOTDIR
Packit 423ecb
        else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOTEMPTY
Packit 423ecb
        else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOTSUP
Packit 423ecb
        else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOTTY
Packit 423ecb
        else if (errno == ENOTTY) code = XML_IO_ENOTTY;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENXIO
Packit 423ecb
        else if (errno == ENXIO) code = XML_IO_ENXIO;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EPERM
Packit 423ecb
        else if (errno == EPERM) code = XML_IO_EPERM;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EPIPE
Packit 423ecb
        else if (errno == EPIPE) code = XML_IO_EPIPE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ERANGE
Packit 423ecb
        else if (errno == ERANGE) code = XML_IO_ERANGE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EROFS
Packit 423ecb
        else if (errno == EROFS) code = XML_IO_EROFS;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ESPIPE
Packit 423ecb
        else if (errno == ESPIPE) code = XML_IO_ESPIPE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ESRCH
Packit 423ecb
        else if (errno == ESRCH) code = XML_IO_ESRCH;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ETIMEDOUT
Packit 423ecb
        else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EXDEV
Packit 423ecb
        else if (errno == EXDEV) code = XML_IO_EXDEV;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENOTSOCK
Packit 423ecb
        else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EISCONN
Packit 423ecb
        else if (errno == EISCONN) code = XML_IO_EISCONN;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ECONNREFUSED
Packit 423ecb
        else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ETIMEDOUT
Packit 423ecb
        else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
Packit 423ecb
#endif
Packit 423ecb
#ifdef ENETUNREACH
Packit 423ecb
        else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EADDRINUSE
Packit 423ecb
        else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EINPROGRESS
Packit 423ecb
        else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EALREADY
Packit 423ecb
        else if (errno == EALREADY) code = XML_IO_EALREADY;
Packit 423ecb
#endif
Packit 423ecb
#ifdef EAFNOSUPPORT
Packit 423ecb
        else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
Packit 423ecb
#endif
Packit 423ecb
        else code = XML_IO_UNKNOWN;
Packit 423ecb
#endif /* HAVE_ERRNO_H */
Packit 423ecb
    }
Packit 423ecb
    idx = 0;
Packit 423ecb
    if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
Packit 423ecb
    if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
Packit 423ecb
Packit 423ecb
    __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOErr:
Packit 423ecb
 * @code:  the error number
Packit 423ecb
 * @extra:  extra informations
Packit 423ecb
 *
Packit 423ecb
 * Handle an I/O error
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
xmlIOErr(int code, const char *extra)
Packit 423ecb
{
Packit 423ecb
    __xmlIOErr(XML_FROM_IO, code, extra);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * __xmlLoaderErr:
Packit 423ecb
 * @ctx: the parser context
Packit 423ecb
 * @extra:  extra informations
Packit 423ecb
 *
Packit 423ecb
 * Handle a resource access error
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
__xmlLoaderErr(void *ctx, const char *msg, const char *filename)
Packit 423ecb
{
Packit 423ecb
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Packit 423ecb
    xmlStructuredErrorFunc schannel = NULL;
Packit 423ecb
    xmlGenericErrorFunc channel = NULL;
Packit 423ecb
    void *data = NULL;
Packit 423ecb
    xmlErrorLevel level = XML_ERR_ERROR;
Packit 423ecb
Packit 423ecb
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
Packit 423ecb
        (ctxt->instate == XML_PARSER_EOF))
Packit 423ecb
	return;
Packit 423ecb
    if ((ctxt != NULL) && (ctxt->sax != NULL)) {
Packit 423ecb
        if (ctxt->validate) {
Packit 423ecb
	    channel = ctxt->sax->error;
Packit 423ecb
	    level = XML_ERR_ERROR;
Packit 423ecb
	} else {
Packit 423ecb
	    channel = ctxt->sax->warning;
Packit 423ecb
	    level = XML_ERR_WARNING;
Packit 423ecb
	}
Packit 423ecb
	if (ctxt->sax->initialized == XML_SAX2_MAGIC)
Packit 423ecb
	    schannel = ctxt->sax->serror;
Packit 423ecb
	data = ctxt->userData;
Packit 423ecb
    }
Packit 423ecb
    __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
Packit 423ecb
                    XML_IO_LOAD_ERROR, level, NULL, 0,
Packit 423ecb
		    filename, NULL, NULL, 0, 0,
Packit 423ecb
		    msg, filename);
Packit 423ecb
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Tree memory error handler				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
/**
Packit 423ecb
 * xmlNormalizeWindowsPath:
Packit 423ecb
 * @path: the input file path
Packit 423ecb
 *
Packit 423ecb
 * This function is obsolete. Please see xmlURIFromPath in uri.c for
Packit 423ecb
 * a better solution.
Packit 423ecb
 *
Packit 423ecb
 * Returns a canonicalized version of the path
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlNormalizeWindowsPath(const xmlChar *path)
Packit 423ecb
{
Packit 423ecb
    return xmlCanonicPath(path);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCleanupInputCallbacks:
Packit 423ecb
 *
Packit 423ecb
 * clears the entire input callback table. this includes the
Packit 423ecb
 * compiled-in I/O.
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlCleanupInputCallbacks(void)
Packit 423ecb
{
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    if (!xmlInputCallbackInitialized)
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
Packit 423ecb
        xmlInputCallbackTable[i].matchcallback = NULL;
Packit 423ecb
        xmlInputCallbackTable[i].opencallback = NULL;
Packit 423ecb
        xmlInputCallbackTable[i].readcallback = NULL;
Packit 423ecb
        xmlInputCallbackTable[i].closecallback = NULL;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    xmlInputCallbackNr = 0;
Packit 423ecb
    xmlInputCallbackInitialized = 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlPopInputCallbacks:
Packit 423ecb
 *
Packit 423ecb
 * Clear the top input callback from the input stack. this includes the
Packit 423ecb
 * compiled-in I/O.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of input callback registered or -1 in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlPopInputCallbacks(void)
Packit 423ecb
{
Packit 423ecb
    if (!xmlInputCallbackInitialized)
Packit 423ecb
        return(-1);
Packit 423ecb
Packit 423ecb
    if (xmlInputCallbackNr <= 0)
Packit 423ecb
        return(-1);
Packit 423ecb
Packit 423ecb
    xmlInputCallbackNr--;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
Packit 423ecb
Packit 423ecb
    return(xmlInputCallbackNr);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlCleanupOutputCallbacks:
Packit 423ecb
 *
Packit 423ecb
 * clears the entire output callback table. this includes the
Packit 423ecb
 * compiled-in I/O callbacks.
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlCleanupOutputCallbacks(void)
Packit 423ecb
{
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    if (!xmlOutputCallbackInitialized)
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
Packit 423ecb
        xmlOutputCallbackTable[i].matchcallback = NULL;
Packit 423ecb
        xmlOutputCallbackTable[i].opencallback = NULL;
Packit 423ecb
        xmlOutputCallbackTable[i].writecallback = NULL;
Packit 423ecb
        xmlOutputCallbackTable[i].closecallback = NULL;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    xmlOutputCallbackNr = 0;
Packit 423ecb
    xmlOutputCallbackInitialized = 0;
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Standard I/O for file accesses				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 *  xmlWrapOpenUtf8:
Packit 423ecb
 * @path:  the path in utf-8 encoding
Packit 423ecb
 * @mode:  type of access (0 - read, 1 - write)
Packit 423ecb
 *
Packit 423ecb
 * function opens the file specified by @path
Packit 423ecb
 *
Packit 423ecb
 */
Packit 423ecb
static FILE*
Packit 423ecb
xmlWrapOpenUtf8(const char *path,int mode)
Packit 423ecb
{
Packit 423ecb
    FILE *fd = NULL;
Packit 423ecb
    wchar_t *wPath;
Packit 423ecb
Packit 423ecb
    wPath = __xmlIOWin32UTF8ToWChar(path);
Packit 423ecb
    if(wPath)
Packit 423ecb
    {
Packit 423ecb
       fd = _wfopen(wPath, mode ? L"wb" : L"rb");
Packit 423ecb
       xmlFree(wPath);
Packit 423ecb
    }
Packit 423ecb
    /* maybe path in native encoding */
Packit 423ecb
    if(fd == NULL)
Packit 423ecb
       fd = fopen(path, mode ? "wb" : "rb");
Packit 423ecb
Packit 423ecb
    return fd;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
static gzFile
Packit 423ecb
xmlWrapGzOpenUtf8(const char *path, const char *mode)
Packit 423ecb
{
Packit 423ecb
    gzFile fd;
Packit 423ecb
    wchar_t *wPath;
Packit 423ecb
Packit 423ecb
    fd = gzopen (path, mode);
Packit 423ecb
    if (fd)
Packit 423ecb
        return fd;
Packit 423ecb
Packit 423ecb
    wPath = __xmlIOWin32UTF8ToWChar(path);
Packit 423ecb
    if(wPath)
Packit 423ecb
    {
Packit 423ecb
	int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
Packit 423ecb
#ifdef _O_BINARY
Packit 423ecb
        m |= (strstr(mode, "b") ? _O_BINARY : 0);
Packit 423ecb
#endif
Packit 423ecb
	d = _wopen(wPath, m);
Packit 423ecb
	if (d >= 0)
Packit 423ecb
	    fd = gzdopen(d, mode);
Packit 423ecb
        xmlFree(wPath);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return fd;
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 *  xmlWrapStatUtf8:
Packit 423ecb
 * @path:  the path in utf-8 encoding
Packit 423ecb
 * @info:  structure that stores results
Packit 423ecb
 *
Packit 423ecb
 * function obtains information about the file or directory
Packit 423ecb
 *
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlWrapStatUtf8(const char *path, struct _stat *info) {
Packit 423ecb
    int retval = -1;
Packit 423ecb
    wchar_t *wPath;
Packit 423ecb
Packit 423ecb
    wPath = __xmlIOWin32UTF8ToWChar(path);
Packit 423ecb
    if (wPath) {
Packit 423ecb
       retval = _wstat(wPath, info);
Packit 423ecb
       xmlFree(wPath);
Packit 423ecb
    }
Packit 423ecb
    /* maybe path in native encoding */
Packit 423ecb
    if(retval < 0)
Packit 423ecb
       retval = _stat(path, info);
Packit 423ecb
    return retval;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCheckFilename:
Packit 423ecb
 * @path:  the path to check
Packit 423ecb
 *
Packit 423ecb
 * function checks to see if @path is a valid source
Packit 423ecb
 * (file, socket...) for XML.
Packit 423ecb
 *
Packit 423ecb
 * if stat is not available on the target machine,
Packit 423ecb
 * returns 1.  if stat fails, returns 0 (if calling
Packit 423ecb
 * stat on the filename fails, it can't be right).
Packit 423ecb
 * if stat succeeds and the file is a directory,
Packit 423ecb
 * returns 2.  otherwise returns 1.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlCheckFilename (const char *path)
Packit 423ecb
{
Packit 423ecb
#ifdef HAVE_STAT
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
    struct _stat stat_buffer;
Packit 423ecb
#else
Packit 423ecb
    struct stat stat_buffer;
Packit 423ecb
#endif
Packit 423ecb
#endif
Packit 423ecb
    if (path == NULL)
Packit 423ecb
	return(0);
Packit 423ecb
Packit 423ecb
#ifdef HAVE_STAT
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
    /*
Packit 423ecb
     * On Windows stat and wstat do not work with long pathname,
Packit 423ecb
     * which start with '\\?\'
Packit 423ecb
     */
Packit 423ecb
    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
Packit 423ecb
	(path[3] == '\\') )
Packit 423ecb
	    return 1;
Packit 423ecb
Packit 423ecb
    if (xmlWrapStatUtf8(path, &stat_buffer) == -1)
Packit 423ecb
        return 0;
Packit 423ecb
#else
Packit 423ecb
    if (stat(path, &stat_buffer) == -1)
Packit 423ecb
        return 0;
Packit 423ecb
#endif
Packit 423ecb
#ifdef S_ISDIR
Packit 423ecb
    if (S_ISDIR(stat_buffer.st_mode))
Packit 423ecb
        return 2;
Packit 423ecb
#endif
Packit 423ecb
#endif /* HAVE_STAT */
Packit 423ecb
    return 1;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlNop:
Packit 423ecb
 *
Packit 423ecb
 * No Operation function, does nothing, no input
Packit 423ecb
 *
Packit 423ecb
 * Returns zero
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlNop(void) {
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFdRead:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to read
Packit 423ecb
 *
Packit 423ecb
 * Read @len bytes to @buffer from the I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlFdRead (void * context, char * buffer, int len) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret = read((int) (ptrdiff_t) context, &buffer[0], len);
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "read()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlFdWrite:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to get data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Write @len bytes from @buffer to the I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlFdWrite (void * context, const char * buffer, int len) {
Packit 423ecb
    int ret = 0;
Packit 423ecb
Packit 423ecb
    if (len > 0) {
Packit 423ecb
	ret = write((int) (ptrdiff_t) context, &buffer[0], len);
Packit 423ecb
	if (ret < 0) xmlIOErr(0, "write()");
Packit 423ecb
    }
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFdClose:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close an I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case of success and error code otherwise
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlFdClose (void * context) {
Packit 423ecb
    int ret;
Packit 423ecb
    ret = close((int) (ptrdiff_t) context);
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "close()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFileMatch:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * input from FILE *
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if matches, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
Packit 423ecb
    return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFileOpen_real:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * input from FILE *, supports compressed input
Packit 423ecb
 * if @filename is " " then the standard input is used
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlFileOpen_real (const char *filename) {
Packit 423ecb
    const char *path = filename;
Packit 423ecb
    FILE *fd;
Packit 423ecb
Packit 423ecb
    if (filename == NULL)
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
    if (!strcmp(filename, "-")) {
Packit 423ecb
	fd = stdin;
Packit 423ecb
	return((void *) fd);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[17];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[16];
Packit 423ecb
#endif
Packit 423ecb
    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[8];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[7];
Packit 423ecb
#endif
Packit 423ecb
    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
Packit 423ecb
        /* lots of generators seems to lazy to read RFC 1738 */
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[6];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[5];
Packit 423ecb
#endif
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /* Do not check DDNAME on zOS ! */
Packit 423ecb
#if !defined(__MVS__)
Packit 423ecb
    if (!xmlCheckFilename(path))
Packit 423ecb
        return(NULL);
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
    fd = xmlWrapOpenUtf8(path, 0);
Packit 423ecb
#else
Packit 423ecb
    fd = fopen(path, "r");
Packit 423ecb
#endif /* WIN32 */
Packit 423ecb
    if (fd == NULL) xmlIOErr(0, path);
Packit 423ecb
    return((void *) fd);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFileOpen:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * Wrapper around xmlFileOpen_real that try it with an unescaped
Packit 423ecb
 * version of @filename, if this fails fallback to @filename
Packit 423ecb
 *
Packit 423ecb
 * Returns a handler or NULL in case or failure
Packit 423ecb
 */
Packit 423ecb
void *
Packit 423ecb
xmlFileOpen (const char *filename) {
Packit 423ecb
    char *unescaped;
Packit 423ecb
    void *retval;
Packit 423ecb
Packit 423ecb
    retval = xmlFileOpen_real(filename);
Packit 423ecb
    if (retval == NULL) {
Packit 423ecb
	unescaped = xmlURIUnescapeString(filename, 0, NULL);
Packit 423ecb
	if (unescaped != NULL) {
Packit 423ecb
	    retval = xmlFileOpen_real(unescaped);
Packit 423ecb
	    xmlFree(unescaped);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return retval;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlFileOpenW:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * output to from FILE *,
Packit 423ecb
 * if @filename is "-" then the standard output is used
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlFileOpenW (const char *filename) {
Packit 423ecb
    const char *path = NULL;
Packit 423ecb
    FILE *fd;
Packit 423ecb
Packit 423ecb
    if (!strcmp(filename, "-")) {
Packit 423ecb
	fd = stdout;
Packit 423ecb
	return((void *) fd);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[17];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[16];
Packit 423ecb
#endif
Packit 423ecb
    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[8];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[7];
Packit 423ecb
#endif
Packit 423ecb
    } else
Packit 423ecb
	path = filename;
Packit 423ecb
Packit 423ecb
    if (path == NULL)
Packit 423ecb
	return(NULL);
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
    fd = xmlWrapOpenUtf8(path, 1);
Packit 423ecb
#elif(__MVS__)
Packit 423ecb
    fd = fopen(path, "w");
Packit 423ecb
#else
Packit 423ecb
    fd = fopen(path, "wb");
Packit 423ecb
#endif /* WIN32 */
Packit 423ecb
Packit 423ecb
    if (fd == NULL) xmlIOErr(0, path);
Packit 423ecb
    return((void *) fd);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFileRead:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Read @len bytes to @buffer from the I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written or < 0 in case of failure
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlFileRead (void * context, char * buffer, int len) {
Packit 423ecb
    int ret;
Packit 423ecb
    if ((context == NULL) || (buffer == NULL))
Packit 423ecb
        return(-1);
Packit 423ecb
    ret = fread(&buffer[0], 1,  len, (FILE *) context);
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "fread()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlFileWrite:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Write @len bytes from @buffer to the I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlFileWrite (void * context, const char * buffer, int len) {
Packit 423ecb
    int items;
Packit 423ecb
Packit 423ecb
    if ((context == NULL) || (buffer == NULL))
Packit 423ecb
        return(-1);
Packit 423ecb
    items = fwrite(&buffer[0], len, 1, (FILE *) context);
Packit 423ecb
    if ((items == 0) && (ferror((FILE *) context))) {
Packit 423ecb
        xmlIOErr(0, "fwrite()");
Packit 423ecb
	return(-1);
Packit 423ecb
    }
Packit 423ecb
    return(items * len);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFileClose:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close an I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlFileClose (void * context) {
Packit 423ecb
    FILE *fil;
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    if (context == NULL)
Packit 423ecb
        return(-1);
Packit 423ecb
    fil = (FILE *) context;
Packit 423ecb
    if ((fil == stdout) || (fil == stderr)) {
Packit 423ecb
        ret = fflush(fil);
Packit 423ecb
	if (ret < 0)
Packit 423ecb
	    xmlIOErr(0, "fflush()");
Packit 423ecb
	return(0);
Packit 423ecb
    }
Packit 423ecb
    if (fil == stdin)
Packit 423ecb
	return(0);
Packit 423ecb
    ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
Packit 423ecb
    if (ret < 0)
Packit 423ecb
        xmlIOErr(0, "fclose()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFileFlush:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Flush an I/O channel
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlFileFlush (void * context) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    if (context == NULL)
Packit 423ecb
        return(-1);
Packit 423ecb
    ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
Packit 423ecb
    if (ret < 0)
Packit 423ecb
        xmlIOErr(0, "fflush()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlBufferWrite:
Packit 423ecb
 * @context:  the xmlBuffer
Packit 423ecb
 * @buffer:  the data to write
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Write @len bytes from @buffer to the xml buffer
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlBufferWrite (void * context, const char * buffer, int len) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
Packit 423ecb
    if (ret != 0)
Packit 423ecb
        return(-1);
Packit 423ecb
    return(len);
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		I/O for compressed file accesses			*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileMatch:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * input from compressed file test
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if matches, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
Packit 423ecb
    return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileOpen_real:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * input from compressed file open
Packit 423ecb
 * if @filename is " " then the standard input is used
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlGzfileOpen_real (const char *filename) {
Packit 423ecb
    const char *path = NULL;
Packit 423ecb
    gzFile fd;
Packit 423ecb
Packit 423ecb
    if (!strcmp(filename, "-")) {
Packit 423ecb
        int duped_fd = dup(fileno(stdin));
Packit 423ecb
        fd = gzdopen(duped_fd, "rb");
Packit 423ecb
        if (fd == Z_NULL && duped_fd >= 0) {
Packit 423ecb
            close(duped_fd);  /* gzdOpen() does not close on failure */
Packit 423ecb
        }
Packit 423ecb
Packit 423ecb
	return((void *) fd);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[17];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[16];
Packit 423ecb
#endif
Packit 423ecb
    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[8];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[7];
Packit 423ecb
#endif
Packit 423ecb
    } else
Packit 423ecb
	path = filename;
Packit 423ecb
Packit 423ecb
    if (path == NULL)
Packit 423ecb
	return(NULL);
Packit 423ecb
    if (!xmlCheckFilename(path))
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
    fd = xmlWrapGzOpenUtf8(path, "rb");
Packit 423ecb
#else
Packit 423ecb
    fd = gzopen(path, "rb");
Packit 423ecb
#endif
Packit 423ecb
    return((void *) fd);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileOpen:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * Wrapper around xmlGzfileOpen if the open fais, it will
Packit 423ecb
 * try to unescape @filename
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlGzfileOpen (const char *filename) {
Packit 423ecb
    char *unescaped;
Packit 423ecb
    void *retval;
Packit 423ecb
Packit 423ecb
    retval = xmlGzfileOpen_real(filename);
Packit 423ecb
    if (retval == NULL) {
Packit 423ecb
	unescaped = xmlURIUnescapeString(filename, 0, NULL);
Packit 423ecb
	if (unescaped != NULL) {
Packit 423ecb
	    retval = xmlGzfileOpen_real(unescaped);
Packit 423ecb
	}
Packit 423ecb
	xmlFree(unescaped);
Packit 423ecb
    }
Packit 423ecb
    return retval;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileOpenW:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 * @compression:  the compression factor (0 - 9 included)
Packit 423ecb
 *
Packit 423ecb
 * input from compressed file open
Packit 423ecb
 * if @filename is " " then the standard input is used
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlGzfileOpenW (const char *filename, int compression) {
Packit 423ecb
    const char *path = NULL;
Packit 423ecb
    char mode[15];
Packit 423ecb
    gzFile fd;
Packit 423ecb
Packit 423ecb
    snprintf(mode, sizeof(mode), "wb%d", compression);
Packit 423ecb
    if (!strcmp(filename, "-")) {
Packit 423ecb
        int duped_fd = dup(fileno(stdout));
Packit 423ecb
        fd = gzdopen(duped_fd, "rb");
Packit 423ecb
        if (fd == Z_NULL && duped_fd >= 0) {
Packit 423ecb
            close(duped_fd);  /* gzdOpen() does not close on failure */
Packit 423ecb
        }
Packit 423ecb
Packit 423ecb
	return((void *) fd);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[17];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[16];
Packit 423ecb
#endif
Packit 423ecb
    else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &filename[8];
Packit 423ecb
#else
Packit 423ecb
	path = &filename[7];
Packit 423ecb
#endif
Packit 423ecb
    } else
Packit 423ecb
	path = filename;
Packit 423ecb
Packit 423ecb
    if (path == NULL)
Packit 423ecb
	return(NULL);
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
Packit 423ecb
    fd = xmlWrapGzOpenUtf8(path, mode);
Packit 423ecb
#else
Packit 423ecb
    fd = gzopen(path, mode);
Packit 423ecb
#endif
Packit 423ecb
    return((void *) fd);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileRead:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Read @len bytes to @buffer from the compressed I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes read.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlGzfileRead (void * context, char * buffer, int len) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret = gzread((gzFile) context, &buffer[0], len);
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "gzread()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileWrite:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Write @len bytes from @buffer to the compressed I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlGzfileWrite (void * context, const char * buffer, int len) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "gzwrite()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlGzfileClose:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close a compressed I/O channel
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlGzfileClose (void * context) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret =  (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "gzclose()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* HAVE_ZLIB_H */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_LZMA_ENABLED
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		I/O for compressed file accesses			*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
#include "xzlib.h"
Packit 423ecb
/**
Packit 423ecb
 * xmlXzfileMatch:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * input from compressed file test
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if matches, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
Packit 423ecb
    return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlXzFileOpen_real:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * input from compressed file open
Packit 423ecb
 * if @filename is " " then the standard input is used
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlXzfileOpen_real (const char *filename) {
Packit 423ecb
    const char *path = NULL;
Packit 423ecb
    xzFile fd;
Packit 423ecb
Packit 423ecb
    if (!strcmp(filename, "-")) {
Packit 423ecb
        fd = __libxml2_xzdopen(dup(fileno(stdin)), "rb");
Packit 423ecb
	return((void *) fd);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
Packit 423ecb
	path = &filename[16];
Packit 423ecb
    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
Packit 423ecb
	path = &filename[7];
Packit 423ecb
    } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
Packit 423ecb
        /* lots of generators seems to lazy to read RFC 1738 */
Packit 423ecb
	path = &filename[5];
Packit 423ecb
    } else
Packit 423ecb
	path = filename;
Packit 423ecb
Packit 423ecb
    if (path == NULL)
Packit 423ecb
	return(NULL);
Packit 423ecb
    if (!xmlCheckFilename(path))
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
    fd = __libxml2_xzopen(path, "rb");
Packit 423ecb
    return((void *) fd);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlXzfileOpen:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * Wrapper around xmlXzfileOpen_real that try it with an unescaped
Packit 423ecb
 * version of @filename, if this fails fallback to @filename
Packit 423ecb
 *
Packit 423ecb
 * Returns a handler or NULL in case or failure
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlXzfileOpen (const char *filename) {
Packit 423ecb
    char *unescaped;
Packit 423ecb
    void *retval;
Packit 423ecb
Packit 423ecb
    retval = xmlXzfileOpen_real(filename);
Packit 423ecb
    if (retval == NULL) {
Packit 423ecb
	unescaped = xmlURIUnescapeString(filename, 0, NULL);
Packit 423ecb
	if (unescaped != NULL) {
Packit 423ecb
	    retval = xmlXzfileOpen_real(unescaped);
Packit 423ecb
	}
Packit 423ecb
	xmlFree(unescaped);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return retval;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlXzfileRead:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Read @len bytes to @buffer from the compressed I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlXzfileRead (void * context, char * buffer, int len) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "xzread()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlXzfileClose:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close a compressed I/O channel
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlXzfileClose (void * context) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret =  (__libxml2_xzclose((xzFile) context) == LZMA_OK ) ? 0 : -1;
Packit 423ecb
    if (ret < 0) xmlIOErr(0, "xzclose()");
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_LZMA_ENABLED */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_HTTP_ENABLED
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *			I/O for HTTP file accesses			*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
typedef struct xmlIOHTTPWriteCtxt_
Packit 423ecb
{
Packit 423ecb
    int			compression;
Packit 423ecb
Packit 423ecb
    char *		uri;
Packit 423ecb
Packit 423ecb
    void *		doc_buff;
Packit 423ecb
Packit 423ecb
} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
Packit 423ecb
#define DFLT_WBITS		( -15 )
Packit 423ecb
#define DFLT_MEM_LVL		( 8 )
Packit 423ecb
#define GZ_MAGIC1		( 0x1f )
Packit 423ecb
#define GZ_MAGIC2		( 0x8b )
Packit 423ecb
#define LXML_ZLIB_OS_CODE	( 0x03 )
Packit 423ecb
#define INIT_HTTP_BUFF_SIZE	( 32768 )
Packit 423ecb
#define DFLT_ZLIB_RATIO		( 5 )
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
**  Data structure and functions to work with sending compressed data
Packit 423ecb
**  via HTTP.
Packit 423ecb
*/
Packit 423ecb
Packit 423ecb
typedef struct xmlZMemBuff_
Packit 423ecb
{
Packit 423ecb
   unsigned long	size;
Packit 423ecb
   unsigned long	crc;
Packit 423ecb
Packit 423ecb
   unsigned char *	zbuff;
Packit 423ecb
   z_stream		zctrl;
Packit 423ecb
Packit 423ecb
} xmlZMemBuff, *xmlZMemBuffPtr;
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * append_reverse_ulong
Packit 423ecb
 * @buff:  Compressed memory buffer
Packit 423ecb
 * @data:  Unsigned long to append
Packit 423ecb
 *
Packit 423ecb
 * Append a unsigned long in reverse byte order to the end of the
Packit 423ecb
 * memory buffer.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
Packit 423ecb
Packit 423ecb
    int		idx;
Packit 423ecb
Packit 423ecb
    if ( buff == NULL )
Packit 423ecb
	return;
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
    **  This is plagiarized from putLong in gzio.c (zlib source) where
Packit 423ecb
    **  the number "4" is hardcoded.  If zlib is ever patched to
Packit 423ecb
    **  support 64 bit file sizes, this code would need to be patched
Packit 423ecb
    **  as well.
Packit 423ecb
    */
Packit 423ecb
Packit 423ecb
    for ( idx = 0; idx < 4; idx++ ) {
Packit 423ecb
	*buff->zctrl.next_out = ( data & 0xff );
Packit 423ecb
	data >>= 8;
Packit 423ecb
	buff->zctrl.next_out++;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 *
Packit 423ecb
 * xmlFreeZMemBuff
Packit 423ecb
 * @buff:  The memory buffer context to clear
Packit 423ecb
 *
Packit 423ecb
 * Release all the resources associated with the compressed memory buffer.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
Packit 423ecb
Packit 423ecb
#ifdef DEBUG_HTTP
Packit 423ecb
    int z_err;
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if ( buff == NULL )
Packit 423ecb
	return;
Packit 423ecb
Packit 423ecb
    xmlFree( buff->zbuff );
Packit 423ecb
#ifdef DEBUG_HTTP
Packit 423ecb
    z_err = deflateEnd( &buff->zctrl );
Packit 423ecb
    if ( z_err != Z_OK )
Packit 423ecb
	xmlGenericError( xmlGenericErrorContext,
Packit 423ecb
			"xmlFreeZMemBuff:  Error releasing zlib context:  %d\n",
Packit 423ecb
			z_err );
Packit 423ecb
#else
Packit 423ecb
    deflateEnd( &buff->zctrl );
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    xmlFree( buff );
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCreateZMemBuff
Packit 423ecb
 *@compression:	Compression value to use
Packit 423ecb
 *
Packit 423ecb
 * Create a memory buffer to hold the compressed XML document.  The
Packit 423ecb
 * compressed document in memory will end up being identical to what
Packit 423ecb
 * would be created if gzopen/gzwrite/gzclose were being used to
Packit 423ecb
 * write the document to disk.  The code for the header/trailer data to
Packit 423ecb
 * the compression is plagiarized from the zlib source files.
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlCreateZMemBuff( int compression ) {
Packit 423ecb
Packit 423ecb
    int			z_err;
Packit 423ecb
    int			hdr_lgth;
Packit 423ecb
    xmlZMemBuffPtr	buff = NULL;
Packit 423ecb
Packit 423ecb
    if ( ( compression < 1 ) || ( compression > 9 ) )
Packit 423ecb
	return ( NULL );
Packit 423ecb
Packit 423ecb
    /*  Create the control and data areas  */
Packit 423ecb
Packit 423ecb
    buff = xmlMalloc( sizeof( xmlZMemBuff ) );
Packit 423ecb
    if ( buff == NULL ) {
Packit 423ecb
	xmlIOErrMemory("creating buffer context");
Packit 423ecb
	return ( NULL );
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
Packit 423ecb
    buff->size = INIT_HTTP_BUFF_SIZE;
Packit 423ecb
    buff->zbuff = xmlMalloc( buff->size );
Packit 423ecb
    if ( buff->zbuff == NULL ) {
Packit 423ecb
	xmlFreeZMemBuff( buff );
Packit 423ecb
	xmlIOErrMemory("creating buffer");
Packit 423ecb
	return ( NULL );
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
Packit 423ecb
			    DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
Packit 423ecb
    if ( z_err != Z_OK ) {
Packit 423ecb
	xmlChar msg[500];
Packit 423ecb
	xmlFreeZMemBuff( buff );
Packit 423ecb
	buff = NULL;
Packit 423ecb
	xmlStrPrintf(msg, 500,
Packit 423ecb
		    "xmlCreateZMemBuff:  %s %d\n",
Packit 423ecb
		    "Error initializing compression context.  ZLIB error:",
Packit 423ecb
		    z_err );
Packit 423ecb
	xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
	return ( NULL );
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*  Set the header data.  The CRC will be needed for the trailer  */
Packit 423ecb
    buff->crc = crc32( 0L, NULL, 0 );
Packit 423ecb
    hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
Packit 423ecb
			"%c%c%c%c%c%c%c%c%c%c",
Packit 423ecb
			GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
Packit 423ecb
			0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
Packit 423ecb
    buff->zctrl.next_out  = buff->zbuff + hdr_lgth;
Packit 423ecb
    buff->zctrl.avail_out = buff->size - hdr_lgth;
Packit 423ecb
Packit 423ecb
    return ( buff );
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlZMemBuffExtend
Packit 423ecb
 * @buff:  Buffer used to compress and consolidate data.
Packit 423ecb
 * @ext_amt:   Number of bytes to extend the buffer.
Packit 423ecb
 *
Packit 423ecb
 * Extend the internal buffer used to store the compressed data by the
Packit 423ecb
 * specified amount.
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 on success or -1 on failure to extend the buffer.  On failure
Packit 423ecb
 * the original buffer still exists at the original size.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
Packit 423ecb
Packit 423ecb
    int			rc = -1;
Packit 423ecb
    size_t		new_size;
Packit 423ecb
    size_t		cur_used;
Packit 423ecb
Packit 423ecb
    unsigned char *	tmp_ptr = NULL;
Packit 423ecb
Packit 423ecb
    if ( buff == NULL )
Packit 423ecb
	return ( -1 );
Packit 423ecb
Packit 423ecb
    else if ( ext_amt == 0 )
Packit 423ecb
	return ( 0 );
Packit 423ecb
Packit 423ecb
    cur_used = buff->zctrl.next_out - buff->zbuff;
Packit 423ecb
    new_size = buff->size + ext_amt;
Packit 423ecb
Packit 423ecb
#ifdef DEBUG_HTTP
Packit 423ecb
    if ( cur_used > new_size )
Packit 423ecb
	xmlGenericError( xmlGenericErrorContext,
Packit 423ecb
			"xmlZMemBuffExtend:  %s\n%s %d bytes.\n",
Packit 423ecb
			"Buffer overwrite detected during compressed memory",
Packit 423ecb
			"buffer extension.  Overflowed by",
Packit 423ecb
			(cur_used - new_size ) );
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    tmp_ptr = xmlRealloc( buff->zbuff, new_size );
Packit 423ecb
    if ( tmp_ptr != NULL ) {
Packit 423ecb
	rc = 0;
Packit 423ecb
	buff->size  = new_size;
Packit 423ecb
	buff->zbuff = tmp_ptr;
Packit 423ecb
	buff->zctrl.next_out  = tmp_ptr + cur_used;
Packit 423ecb
	buff->zctrl.avail_out = new_size - cur_used;
Packit 423ecb
    }
Packit 423ecb
    else {
Packit 423ecb
	xmlChar msg[500];
Packit 423ecb
	xmlStrPrintf(msg, 500,
Packit 423ecb
		    "xmlZMemBuffExtend:  %s %lu bytes.\n",
Packit 423ecb
		    "Allocation failure extending output buffer to",
Packit 423ecb
		    (unsigned long) new_size );
Packit 423ecb
	xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return ( rc );
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlZMemBuffAppend
Packit 423ecb
 * @buff:  Buffer used to compress and consolidate data
Packit 423ecb
 * @src:   Uncompressed source content to append to buffer
Packit 423ecb
 * @len:   Length of source data to append to buffer
Packit 423ecb
 *
Packit 423ecb
 * Compress and append data to the internal buffer.  The data buffer
Packit 423ecb
 * will be expanded if needed to store the additional data.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes appended to the buffer or -1 on error.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
Packit 423ecb
Packit 423ecb
    int		z_err;
Packit 423ecb
    size_t	min_accept;
Packit 423ecb
Packit 423ecb
    if ( ( buff == NULL ) || ( src == NULL ) )
Packit 423ecb
	return ( -1 );
Packit 423ecb
Packit 423ecb
    buff->zctrl.avail_in = len;
Packit 423ecb
    buff->zctrl.next_in  = (unsigned char *)src;
Packit 423ecb
    while ( buff->zctrl.avail_in > 0 ) {
Packit 423ecb
	/*
Packit 423ecb
	**  Extend the buffer prior to deflate call if a reasonable amount
Packit 423ecb
	**  of output buffer space is not available.
Packit 423ecb
	*/
Packit 423ecb
	min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
Packit 423ecb
	if ( buff->zctrl.avail_out <= min_accept ) {
Packit 423ecb
	    if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
Packit 423ecb
		return ( -1 );
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
	z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
Packit 423ecb
	if ( z_err != Z_OK ) {
Packit 423ecb
	    xmlChar msg[500];
Packit 423ecb
	    xmlStrPrintf(msg, 500,
Packit 423ecb
			"xmlZMemBuffAppend:  %s %d %s - %d",
Packit 423ecb
			"Compression error while appending",
Packit 423ecb
			len, "bytes to buffer.  ZLIB error", z_err );
Packit 423ecb
	    xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
	    return ( -1 );
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    buff->crc = crc32( buff->crc, (unsigned char *)src, len );
Packit 423ecb
Packit 423ecb
    return ( len );
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlZMemBuffGetContent
Packit 423ecb
 * @buff:  Compressed memory content buffer
Packit 423ecb
 * @data_ref:  Pointer reference to point to compressed content
Packit 423ecb
 *
Packit 423ecb
 * Flushes the compression buffers, appends gzip file trailers and
Packit 423ecb
 * returns the compressed content and length of the compressed data.
Packit 423ecb
 * NOTE:  The gzip trailer code here is plagiarized from zlib source.
Packit 423ecb
 *
Packit 423ecb
 * Returns the length of the compressed data or -1 on error.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
Packit 423ecb
Packit 423ecb
    int		zlgth = -1;
Packit 423ecb
    int		z_err;
Packit 423ecb
Packit 423ecb
    if ( ( buff == NULL ) || ( data_ref == NULL ) )
Packit 423ecb
	return ( -1 );
Packit 423ecb
Packit 423ecb
    /*  Need to loop until compression output buffers are flushed  */
Packit 423ecb
Packit 423ecb
    do
Packit 423ecb
    {
Packit 423ecb
	z_err = deflate( &buff->zctrl, Z_FINISH );
Packit 423ecb
	if ( z_err == Z_OK ) {
Packit 423ecb
	    /*  In this case Z_OK means more buffer space needed  */
Packit 423ecb
Packit 423ecb
	    if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
Packit 423ecb
		return ( -1 );
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    while ( z_err == Z_OK );
Packit 423ecb
Packit 423ecb
    /*  If the compression state is not Z_STREAM_END, some error occurred  */
Packit 423ecb
Packit 423ecb
    if ( z_err == Z_STREAM_END ) {
Packit 423ecb
Packit 423ecb
	/*  Need to append the gzip data trailer  */
Packit 423ecb
Packit 423ecb
	if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
Packit 423ecb
	    if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
Packit 423ecb
		return ( -1 );
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	**  For whatever reason, the CRC and length data are pushed out
Packit 423ecb
	**  in reverse byte order.  So a memcpy can't be used here.
Packit 423ecb
	*/
Packit 423ecb
Packit 423ecb
	append_reverse_ulong( buff, buff->crc );
Packit 423ecb
	append_reverse_ulong( buff, buff->zctrl.total_in );
Packit 423ecb
Packit 423ecb
	zlgth = buff->zctrl.next_out - buff->zbuff;
Packit 423ecb
	*data_ref = (char *)buff->zbuff;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    else {
Packit 423ecb
	xmlChar msg[500];
Packit 423ecb
	xmlStrPrintf(msg, 500,
Packit 423ecb
		    "xmlZMemBuffGetContent:  %s - %d\n",
Packit 423ecb
		    "Error flushing zlib buffers.  Error code", z_err );
Packit 423ecb
	xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return ( zlgth );
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
#endif  /*  HAVE_ZLIB_H  */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlFreeHTTPWriteCtxt
Packit 423ecb
 * @ctxt:  Context to cleanup
Packit 423ecb
 *
Packit 423ecb
 * Free allocated memory and reclaim system resources.
Packit 423ecb
 *
Packit 423ecb
 * No return value.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
Packit 423ecb
{
Packit 423ecb
    if ( ctxt->uri != NULL )
Packit 423ecb
	xmlFree( ctxt->uri );
Packit 423ecb
Packit 423ecb
    if ( ctxt->doc_buff != NULL ) {
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
	if ( ctxt->compression > 0 ) {
Packit 423ecb
	    xmlFreeZMemBuff( ctxt->doc_buff );
Packit 423ecb
	}
Packit 423ecb
	else
Packit 423ecb
#endif
Packit 423ecb
	{
Packit 423ecb
	    xmlOutputBufferClose( ctxt->doc_buff );
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    xmlFree( ctxt );
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPMatch:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * check if the URI matches an HTTP one
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if matches, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlIOHTTPMatch (const char *filename) {
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
Packit 423ecb
	return(1);
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPOpen:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * open an HTTP I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
void *
Packit 423ecb
xmlIOHTTPOpen (const char *filename) {
Packit 423ecb
    return(xmlNanoHTTPOpen(filename, NULL));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPOpenW:
Packit 423ecb
 * @post_uri:  The destination URI for the document
Packit 423ecb
 * @compression:  The compression desired for the document.
Packit 423ecb
 *
Packit 423ecb
 * Open a temporary buffer to collect the document for a subsequent HTTP POST
Packit 423ecb
 * request.  Non-static as is called from the output buffer creation routine.
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
void *
Packit 423ecb
xmlIOHTTPOpenW(const char *post_uri, int compression ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
Packit 423ecb
    xmlIOHTTPWriteCtxtPtr ctxt = NULL;
Packit 423ecb
Packit 423ecb
    if (post_uri == NULL)
Packit 423ecb
        return (NULL);
Packit 423ecb
Packit 423ecb
    ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
Packit 423ecb
    if (ctxt == NULL) {
Packit 423ecb
	xmlIOErrMemory("creating HTTP output context");
Packit 423ecb
        return (NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
Packit 423ecb
Packit 423ecb
    ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
Packit 423ecb
    if (ctxt->uri == NULL) {
Packit 423ecb
	xmlIOErrMemory("copying URI");
Packit 423ecb
        xmlFreeHTTPWriteCtxt(ctxt);
Packit 423ecb
        return (NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * **  Since the document length is required for an HTTP post,
Packit 423ecb
     * **  need to put the document into a buffer.  A memory buffer
Packit 423ecb
     * **  is being used to avoid pushing the data to disk and back.
Packit 423ecb
     */
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
    if ((compression > 0) && (compression <= 9)) {
Packit 423ecb
Packit 423ecb
        ctxt->compression = compression;
Packit 423ecb
        ctxt->doc_buff = xmlCreateZMemBuff(compression);
Packit 423ecb
    } else
Packit 423ecb
#endif
Packit 423ecb
    {
Packit 423ecb
        /*  Any character conversions should have been done before this  */
Packit 423ecb
Packit 423ecb
        ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (ctxt->doc_buff == NULL) {
Packit 423ecb
        xmlFreeHTTPWriteCtxt(ctxt);
Packit 423ecb
        ctxt = NULL;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return (ctxt);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPDfltOpenW
Packit 423ecb
 * @post_uri:  The destination URI for this document.
Packit 423ecb
 *
Packit 423ecb
 * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
Packit 423ecb
 * HTTP post command.  This function should generally not be used as
Packit 423ecb
 * the open callback is short circuited in xmlOutputBufferCreateFile.
Packit 423ecb
 *
Packit 423ecb
 * Returns a pointer to the new IO context.
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
xmlIOHTTPDfltOpenW( const char * post_uri ) {
Packit 423ecb
    return ( xmlIOHTTPOpenW( post_uri, 0 ) );
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPRead:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Read @len bytes to @buffer from the I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlIOHTTPRead(void * context, char * buffer, int len) {
Packit 423ecb
    if ((buffer == NULL) || (len < 0)) return(-1);
Packit 423ecb
    return(xmlNanoHTTPRead(context, &buffer[0], len));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPWrite
Packit 423ecb
 * @context:  previously opened writing context
Packit 423ecb
 * @buffer:   data to output to temporary buffer
Packit 423ecb
 * @len:      bytes to output
Packit 423ecb
 *
Packit 423ecb
 * Collect data from memory buffer into a temporary file for later
Packit 423ecb
 * processing.
Packit 423ecb
 *
Packit 423ecb
 * Returns number of bytes written.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
static int
Packit 423ecb
xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
Packit 423ecb
Packit 423ecb
    xmlIOHTTPWriteCtxtPtr	ctxt = context;
Packit 423ecb
Packit 423ecb
    if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
Packit 423ecb
	return ( -1 );
Packit 423ecb
Packit 423ecb
    if ( len > 0 ) {
Packit 423ecb
Packit 423ecb
	/*  Use gzwrite or fwrite as previously setup in the open call  */
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
	if ( ctxt->compression > 0 )
Packit 423ecb
	    len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
Packit 423ecb
Packit 423ecb
	else
Packit 423ecb
#endif
Packit 423ecb
	    len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
Packit 423ecb
Packit 423ecb
	if ( len < 0 ) {
Packit 423ecb
	    xmlChar msg[500];
Packit 423ecb
	    xmlStrPrintf(msg, 500,
Packit 423ecb
			"xmlIOHTTPWrite:  %s\n%s '%s'.\n",
Packit 423ecb
			"Error appending to internal buffer.",
Packit 423ecb
			"Error sending document to URI",
Packit 423ecb
			ctxt->uri );
Packit 423ecb
	    xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return ( len );
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPClose:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close an HTTP I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns 0
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlIOHTTPClose (void * context) {
Packit 423ecb
    xmlNanoHTTPClose(context);
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTCloseWrite
Packit 423ecb
 * @context:  The I/O context
Packit 423ecb
 * @http_mthd: The HTTP method to be used when sending the data
Packit 423ecb
 *
Packit 423ecb
 * Close the transmit HTTP I/O channel and actually send the data.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
Packit 423ecb
Packit 423ecb
    int				close_rc = -1;
Packit 423ecb
    int				http_rtn = 0;
Packit 423ecb
    int				content_lgth = 0;
Packit 423ecb
    xmlIOHTTPWriteCtxtPtr	ctxt = context;
Packit 423ecb
Packit 423ecb
    char *			http_content = NULL;
Packit 423ecb
    char *			content_encoding = NULL;
Packit 423ecb
    char *			content_type = (char *) "text/xml";
Packit 423ecb
    void *			http_ctxt = NULL;
Packit 423ecb
Packit 423ecb
    if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
Packit 423ecb
	return ( -1 );
Packit 423ecb
Packit 423ecb
    /*  Retrieve the content from the appropriate buffer  */
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
Packit 423ecb
    if ( ctxt->compression > 0 ) {
Packit 423ecb
	content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
Packit 423ecb
	content_encoding = (char *) "Content-Encoding: gzip";
Packit 423ecb
    }
Packit 423ecb
    else
Packit 423ecb
#endif
Packit 423ecb
    {
Packit 423ecb
	/*  Pull the data out of the memory output buffer  */
Packit 423ecb
Packit 423ecb
	xmlOutputBufferPtr	dctxt = ctxt->doc_buff;
Packit 423ecb
	http_content = (char *) xmlBufContent(dctxt->buffer);
Packit 423ecb
	content_lgth = xmlBufUse(dctxt->buffer);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if ( http_content == NULL ) {
Packit 423ecb
	xmlChar msg[500];
Packit 423ecb
	xmlStrPrintf(msg, 500,
Packit 423ecb
		     "xmlIOHTTPCloseWrite:  %s '%s' %s '%s'.\n",
Packit 423ecb
		     "Error retrieving content.\nUnable to",
Packit 423ecb
		     http_mthd, "data to URI", ctxt->uri );
Packit 423ecb
	xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    else {
Packit 423ecb
Packit 423ecb
	http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
Packit 423ecb
					&content_type, content_encoding,
Packit 423ecb
					content_lgth );
Packit 423ecb
Packit 423ecb
	if ( http_ctxt != NULL ) {
Packit 423ecb
#ifdef DEBUG_HTTP
Packit 423ecb
	    /*  If testing/debugging - dump reply with request content  */
Packit 423ecb
Packit 423ecb
	    FILE *	tst_file = NULL;
Packit 423ecb
	    char	buffer[ 4096 ];
Packit 423ecb
	    char *	dump_name = NULL;
Packit 423ecb
	    int		avail;
Packit 423ecb
Packit 423ecb
	    xmlGenericError( xmlGenericErrorContext,
Packit 423ecb
			"xmlNanoHTTPCloseWrite:  HTTP %s to\n%s returned %d.\n",
Packit 423ecb
			http_mthd, ctxt->uri,
Packit 423ecb
			xmlNanoHTTPReturnCode( http_ctxt ) );
Packit 423ecb
Packit 423ecb
	    /*
Packit 423ecb
	    **  Since either content or reply may be gzipped,
Packit 423ecb
	    **  dump them to separate files instead of the
Packit 423ecb
	    **  standard error context.
Packit 423ecb
	    */
Packit 423ecb
Packit 423ecb
	    dump_name = tempnam( NULL, "lxml" );
Packit 423ecb
	    if ( dump_name != NULL ) {
Packit 423ecb
		(void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
Packit 423ecb
Packit 423ecb
		tst_file = fopen( buffer, "wb" );
Packit 423ecb
		if ( tst_file != NULL ) {
Packit 423ecb
		    xmlGenericError( xmlGenericErrorContext,
Packit 423ecb
			"Transmitted content saved in file:  %s\n", buffer );
Packit 423ecb
Packit 423ecb
		    fwrite( http_content, sizeof( char ),
Packit 423ecb
					content_lgth, tst_file );
Packit 423ecb
		    fclose( tst_file );
Packit 423ecb
		}
Packit 423ecb
Packit 423ecb
		(void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
Packit 423ecb
		tst_file = fopen( buffer, "wb" );
Packit 423ecb
		if ( tst_file != NULL ) {
Packit 423ecb
		    xmlGenericError( xmlGenericErrorContext,
Packit 423ecb
			"Reply content saved in file:  %s\n", buffer );
Packit 423ecb
Packit 423ecb
Packit 423ecb
		    while ( (avail = xmlNanoHTTPRead( http_ctxt,
Packit 423ecb
					buffer, sizeof( buffer ) )) > 0 ) {
Packit 423ecb
Packit 423ecb
			fwrite( buffer, sizeof( char ), avail, tst_file );
Packit 423ecb
		    }
Packit 423ecb
Packit 423ecb
		    fclose( tst_file );
Packit 423ecb
		}
Packit 423ecb
Packit 423ecb
		free( dump_name );
Packit 423ecb
	    }
Packit 423ecb
#endif  /*  DEBUG_HTTP  */
Packit 423ecb
Packit 423ecb
	    http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
Packit 423ecb
	    if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
Packit 423ecb
		close_rc = 0;
Packit 423ecb
	    else {
Packit 423ecb
                xmlChar msg[500];
Packit 423ecb
                xmlStrPrintf(msg, 500,
Packit 423ecb
                      "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
Packit 423ecb
			    http_mthd, content_lgth,
Packit 423ecb
			    "bytes to URI", ctxt->uri,
Packit 423ecb
			    "failed.  HTTP return code:", http_rtn );
Packit 423ecb
		xmlIOErr(XML_IO_WRITE, (const char *) msg);
Packit 423ecb
            }
Packit 423ecb
Packit 423ecb
	    xmlNanoHTTPClose( http_ctxt );
Packit 423ecb
	    xmlFree( content_type );
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*  Final cleanups  */
Packit 423ecb
Packit 423ecb
    xmlFreeHTTPWriteCtxt( ctxt );
Packit 423ecb
Packit 423ecb
    return ( close_rc );
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPClosePut
Packit 423ecb
 *
Packit 423ecb
 * @context:  The I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close the transmit HTTP I/O channel and actually send data using a PUT
Packit 423ecb
 * HTTP method.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlIOHTTPClosePut( void * ctxt ) {
Packit 423ecb
    return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOHTTPClosePost
Packit 423ecb
 *
Packit 423ecb
 * @context:  The I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close the transmit HTTP I/O channel and actually send data using a POST
Packit 423ecb
 * HTTP method.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlIOHTTPClosePost( void * ctxt ) {
Packit 423ecb
    return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
#endif /* LIBXML_HTTP_ENABLED */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_FTP_ENABLED
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *			I/O for FTP file accesses			*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
/**
Packit 423ecb
 * xmlIOFTPMatch:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * check if the URI matches an FTP one
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if matches, 0 otherwise
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlIOFTPMatch (const char *filename) {
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
Packit 423ecb
	return(1);
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOFTPOpen:
Packit 423ecb
 * @filename:  the URI for matching
Packit 423ecb
 *
Packit 423ecb
 * open an FTP I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns an I/O context or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
void *
Packit 423ecb
xmlIOFTPOpen (const char *filename) {
Packit 423ecb
    return(xmlNanoFTPOpen(filename));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOFTPRead:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 * @buffer:  where to drop data
Packit 423ecb
 * @len:  number of bytes to write
Packit 423ecb
 *
Packit 423ecb
 * Read @len bytes to @buffer from the I/O channel.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes written
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlIOFTPRead(void * context, char * buffer, int len) {
Packit 423ecb
    if ((buffer == NULL) || (len < 0)) return(-1);
Packit 423ecb
    return(xmlNanoFTPRead(context, &buffer[0], len));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlIOFTPClose:
Packit 423ecb
 * @context:  the I/O context
Packit 423ecb
 *
Packit 423ecb
 * Close an FTP I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns 0
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlIOFTPClose (void * context) {
Packit 423ecb
    return ( xmlNanoFTPClose(context) );
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_FTP_ENABLED */
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlRegisterInputCallbacks:
Packit 423ecb
 * @matchFunc:  the xmlInputMatchCallback
Packit 423ecb
 * @openFunc:  the xmlInputOpenCallback
Packit 423ecb
 * @readFunc:  the xmlInputReadCallback
Packit 423ecb
 * @closeFunc:  the xmlInputCloseCallback
Packit 423ecb
 *
Packit 423ecb
 * Register a new set of I/O callback for handling parser input.
Packit 423ecb
 *
Packit 423ecb
 * Returns the registered handler number or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
Packit 423ecb
	xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
Packit 423ecb
	xmlInputCloseCallback closeFunc) {
Packit 423ecb
    if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
Packit 423ecb
	return(-1);
Packit 423ecb
    }
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
Packit 423ecb
    xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
Packit 423ecb
    xmlInputCallbackInitialized = 1;
Packit 423ecb
    return(xmlInputCallbackNr++);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlRegisterOutputCallbacks:
Packit 423ecb
 * @matchFunc:  the xmlOutputMatchCallback
Packit 423ecb
 * @openFunc:  the xmlOutputOpenCallback
Packit 423ecb
 * @writeFunc:  the xmlOutputWriteCallback
Packit 423ecb
 * @closeFunc:  the xmlOutputCloseCallback
Packit 423ecb
 *
Packit 423ecb
 * Register a new set of I/O callback for handling output.
Packit 423ecb
 *
Packit 423ecb
 * Returns the registered handler number or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
Packit 423ecb
	xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
Packit 423ecb
	xmlOutputCloseCallback closeFunc) {
Packit 423ecb
    if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
Packit 423ecb
	return(-1);
Packit 423ecb
    }
Packit 423ecb
    xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
Packit 423ecb
    xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
Packit 423ecb
    xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
Packit 423ecb
    xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
Packit 423ecb
    xmlOutputCallbackInitialized = 1;
Packit 423ecb
    return(xmlOutputCallbackNr++);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlRegisterDefaultInputCallbacks:
Packit 423ecb
 *
Packit 423ecb
 * Registers the default compiled-in I/O handlers.
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlRegisterDefaultInputCallbacks(void) {
Packit 423ecb
    if (xmlInputCallbackInitialized)
Packit 423ecb
	return;
Packit 423ecb
Packit 423ecb
    xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
Packit 423ecb
	                      xmlFileRead, xmlFileClose);
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
    xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
Packit 423ecb
	                      xmlGzfileRead, xmlGzfileClose);
Packit 423ecb
#endif /* HAVE_ZLIB_H */
Packit 423ecb
#ifdef LIBXML_LZMA_ENABLED
Packit 423ecb
    xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen,
Packit 423ecb
	                      xmlXzfileRead, xmlXzfileClose);
Packit 423ecb
#endif /* LIBXML_LZMA_ENABLED */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_HTTP_ENABLED
Packit 423ecb
    xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
Packit 423ecb
	                      xmlIOHTTPRead, xmlIOHTTPClose);
Packit 423ecb
#endif /* LIBXML_HTTP_ENABLED */
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_FTP_ENABLED
Packit 423ecb
    xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
Packit 423ecb
	                      xmlIOFTPRead, xmlIOFTPClose);
Packit 423ecb
#endif /* LIBXML_FTP_ENABLED */
Packit 423ecb
    xmlInputCallbackInitialized = 1;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlRegisterDefaultOutputCallbacks:
Packit 423ecb
 *
Packit 423ecb
 * Registers the default compiled-in I/O handlers.
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlRegisterDefaultOutputCallbacks (void) {
Packit 423ecb
    if (xmlOutputCallbackInitialized)
Packit 423ecb
	return;
Packit 423ecb
Packit 423ecb
    xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
Packit 423ecb
	                      xmlFileWrite, xmlFileClose);
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_HTTP_ENABLED
Packit 423ecb
    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
Packit 423ecb
	                       xmlIOHTTPWrite, xmlIOHTTPClosePut);
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/*********************************
Packit 423ecb
 No way a-priori to distinguish between gzipped files from
Packit 423ecb
 uncompressed ones except opening if existing then closing
Packit 423ecb
 and saving with same compression ratio ... a pain.
Packit 423ecb
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
    xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
Packit 423ecb
	                       xmlGzfileWrite, xmlGzfileClose);
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
 Nor FTP PUT ....
Packit 423ecb
#ifdef LIBXML_FTP_ENABLED
Packit 423ecb
    xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
Packit 423ecb
	                       xmlIOFTPWrite, xmlIOFTPClose);
Packit 423ecb
#endif
Packit 423ecb
 **********************************/
Packit 423ecb
    xmlOutputCallbackInitialized = 1;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_HTTP_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlRegisterHTTPPostCallbacks:
Packit 423ecb
 *
Packit 423ecb
 * By default, libxml submits HTTP output requests using the "PUT" method.
Packit 423ecb
 * Calling this method changes the HTTP output method to use the "POST"
Packit 423ecb
 * method instead.
Packit 423ecb
 *
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlRegisterHTTPPostCallbacks( void ) {
Packit 423ecb
Packit 423ecb
    /*  Register defaults if not done previously  */
Packit 423ecb
Packit 423ecb
    if ( xmlOutputCallbackInitialized == 0 )
Packit 423ecb
	xmlRegisterDefaultOutputCallbacks( );
Packit 423ecb
Packit 423ecb
    xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
Packit 423ecb
	                       xmlIOHTTPWrite, xmlIOHTTPClosePost);
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlAllocParserInputBuffer:
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for progressive parsing
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlAllocParserInputBuffer(xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
	xmlIOErrMemory("creating input buffer");
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
Packit 423ecb
    ret->buffer = xmlBufCreateSize(2 * xmlDefaultBufferSize);
Packit 423ecb
    if (ret->buffer == NULL) {
Packit 423ecb
        xmlFree(ret);
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
    xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
Packit 423ecb
    ret->encoder = xmlGetCharEncodingHandler(enc);
Packit 423ecb
    if (ret->encoder != NULL)
Packit 423ecb
        ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
Packit 423ecb
    else
Packit 423ecb
        ret->raw = NULL;
Packit 423ecb
    ret->readcallback = NULL;
Packit 423ecb
    ret->closecallback = NULL;
Packit 423ecb
    ret->context = NULL;
Packit 423ecb
    ret->compressed = -1;
Packit 423ecb
    ret->rawconsumed = 0;
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlAllocOutputBuffer:
Packit 423ecb
 * @encoder:  the encoding converter or NULL
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser output
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
	xmlIOErrMemory("creating output buffer");
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
    memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
Packit 423ecb
    ret->buffer = xmlBufCreate();
Packit 423ecb
    if (ret->buffer == NULL) {
Packit 423ecb
        xmlFree(ret);
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /* try to avoid a performance problem with Windows realloc() */
Packit 423ecb
    if (xmlBufGetAllocationScheme(ret->buffer) == XML_BUFFER_ALLOC_EXACT)
Packit 423ecb
        xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
Packit 423ecb
Packit 423ecb
    ret->encoder = encoder;
Packit 423ecb
    if (encoder != NULL) {
Packit 423ecb
        ret->conv = xmlBufCreateSize(4000);
Packit 423ecb
	if (ret->conv == NULL) {
Packit 423ecb
	    xmlFree(ret);
Packit 423ecb
	    return(NULL);
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * This call is designed to initiate the encoder state
Packit 423ecb
	 */
Packit 423ecb
	xmlCharEncOutput(ret, 1);
Packit 423ecb
    } else
Packit 423ecb
        ret->conv = NULL;
Packit 423ecb
    ret->writecallback = NULL;
Packit 423ecb
    ret->closecallback = NULL;
Packit 423ecb
    ret->context = NULL;
Packit 423ecb
    ret->written = 0;
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlAllocOutputBufferInternal:
Packit 423ecb
 * @encoder:  the encoding converter or NULL
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser output
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
	xmlIOErrMemory("creating output buffer");
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
    memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
Packit 423ecb
    ret->buffer = xmlBufCreate();
Packit 423ecb
    if (ret->buffer == NULL) {
Packit 423ecb
        xmlFree(ret);
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * For conversion buffers we use the special IO handling
Packit 423ecb
     */
Packit 423ecb
    xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_IO);
Packit 423ecb
Packit 423ecb
    ret->encoder = encoder;
Packit 423ecb
    if (encoder != NULL) {
Packit 423ecb
        ret->conv = xmlBufCreateSize(4000);
Packit 423ecb
	if (ret->conv == NULL) {
Packit 423ecb
	    xmlFree(ret);
Packit 423ecb
	    return(NULL);
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * This call is designed to initiate the encoder state
Packit 423ecb
	 */
Packit 423ecb
        xmlCharEncOutput(ret, 1);
Packit 423ecb
    } else
Packit 423ecb
        ret->conv = NULL;
Packit 423ecb
    ret->writecallback = NULL;
Packit 423ecb
    ret->closecallback = NULL;
Packit 423ecb
    ret->context = NULL;
Packit 423ecb
    ret->written = 0;
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlFreeParserInputBuffer:
Packit 423ecb
 * @in:  a buffered parser input
Packit 423ecb
 *
Packit 423ecb
 * Free up the memory used by a buffered parser input
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
Packit 423ecb
    if (in == NULL) return;
Packit 423ecb
Packit 423ecb
    if (in->raw) {
Packit 423ecb
        xmlBufFree(in->raw);
Packit 423ecb
	in->raw = NULL;
Packit 423ecb
    }
Packit 423ecb
    if (in->encoder != NULL) {
Packit 423ecb
        xmlCharEncCloseFunc(in->encoder);
Packit 423ecb
    }
Packit 423ecb
    if (in->closecallback != NULL) {
Packit 423ecb
	in->closecallback(in->context);
Packit 423ecb
    }
Packit 423ecb
    if (in->buffer != NULL) {
Packit 423ecb
        xmlBufFree(in->buffer);
Packit 423ecb
	in->buffer = NULL;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    xmlFree(in);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferClose:
Packit 423ecb
 * @out:  a buffered output
Packit 423ecb
 *
Packit 423ecb
 * flushes and close the output I/O channel
Packit 423ecb
 * and free up all the associated resources
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of byte written or -1 in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlOutputBufferClose(xmlOutputBufferPtr out)
Packit 423ecb
{
Packit 423ecb
    int written;
Packit 423ecb
    int err_rc = 0;
Packit 423ecb
Packit 423ecb
    if (out == NULL)
Packit 423ecb
        return (-1);
Packit 423ecb
    if (out->writecallback != NULL)
Packit 423ecb
        xmlOutputBufferFlush(out);
Packit 423ecb
    if (out->closecallback != NULL) {
Packit 423ecb
        err_rc = out->closecallback(out->context);
Packit 423ecb
    }
Packit 423ecb
    written = out->written;
Packit 423ecb
    if (out->conv) {
Packit 423ecb
        xmlBufFree(out->conv);
Packit 423ecb
        out->conv = NULL;
Packit 423ecb
    }
Packit 423ecb
    if (out->encoder != NULL) {
Packit 423ecb
        xmlCharEncCloseFunc(out->encoder);
Packit 423ecb
    }
Packit 423ecb
    if (out->buffer != NULL) {
Packit 423ecb
        xmlBufFree(out->buffer);
Packit 423ecb
        out->buffer = NULL;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (out->error)
Packit 423ecb
        err_rc = -1;
Packit 423ecb
    xmlFree(out);
Packit 423ecb
    return ((err_rc == 0) ? written : err_rc);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
    int i = 0;
Packit 423ecb
    void *context = NULL;
Packit 423ecb
Packit 423ecb
    if (xmlInputCallbackInitialized == 0)
Packit 423ecb
	xmlRegisterDefaultInputCallbacks();
Packit 423ecb
Packit 423ecb
    if (URI == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Try to find one of the input accept method accepting that scheme
Packit 423ecb
     * Go in reverse to give precedence to user defined handlers.
Packit 423ecb
     */
Packit 423ecb
    if (context == NULL) {
Packit 423ecb
	for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
Packit 423ecb
	    if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
Packit 423ecb
		(xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
Packit 423ecb
		context = xmlInputCallbackTable[i].opencallback(URI);
Packit 423ecb
		if (context != NULL) {
Packit 423ecb
		    break;
Packit 423ecb
		}
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    if (context == NULL) {
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Allocate the Input buffer front-end.
Packit 423ecb
     */
Packit 423ecb
    ret = xmlAllocParserInputBuffer(enc);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
	ret->context = context;
Packit 423ecb
	ret->readcallback = xmlInputCallbackTable[i].readcallback;
Packit 423ecb
	ret->closecallback = xmlInputCallbackTable[i].closecallback;
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
	if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
Packit 423ecb
		(strcmp(URI, "-") != 0)) {
Packit 423ecb
#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
Packit 423ecb
            ret->compressed = !gzdirect(context);
Packit 423ecb
#else
Packit 423ecb
	    if (((z_stream *)context)->avail_in > 4) {
Packit 423ecb
	        char *cptr, buff4[4];
Packit 423ecb
		cptr = (char *) ((z_stream *)context)->next_in;
Packit 423ecb
		if (gzread(context, buff4, 4) == 4) {
Packit 423ecb
		    if (strncmp(buff4, cptr, 4) == 0)
Packit 423ecb
		        ret->compressed = 0;
Packit 423ecb
		    else
Packit 423ecb
		        ret->compressed = 1;
Packit 423ecb
		    gzrewind(context);
Packit 423ecb
		}
Packit 423ecb
	    }
Packit 423ecb
#endif
Packit 423ecb
	}
Packit 423ecb
#endif
Packit 423ecb
#ifdef LIBXML_LZMA_ENABLED
Packit 423ecb
	if ((xmlInputCallbackTable[i].opencallback == xmlXzfileOpen) &&
Packit 423ecb
		(strcmp(URI, "-") != 0)) {
Packit 423ecb
            ret->compressed = __libxml2_xzcompressed(context);
Packit 423ecb
	}
Packit 423ecb
#endif
Packit 423ecb
    }
Packit 423ecb
    else
Packit 423ecb
      xmlInputCallbackTable[i].closecallback (context);
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateFilename:
Packit 423ecb
 * @URI:  a C string containing the URI or filename
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for the progressive parsing of a file
Packit 423ecb
 * If filename is "-' then we use stdin as the input.
Packit 423ecb
 * Automatic support for ZLIB/Compress compressed document is provided
Packit 423ecb
 * by default if found at compile-time.
Packit 423ecb
 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
Packit 423ecb
    if ((xmlParserInputBufferCreateFilenameValue)) {
Packit 423ecb
		return xmlParserInputBufferCreateFilenameValue(URI, enc);
Packit 423ecb
	}
Packit 423ecb
	return __xmlParserInputBufferCreateFilename(URI, enc);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
__xmlOutputBufferCreateFilename(const char *URI,
Packit 423ecb
                              xmlCharEncodingHandlerPtr encoder,
Packit 423ecb
                              int compression ATTRIBUTE_UNUSED) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
    xmlURIPtr puri;
Packit 423ecb
    int i = 0;
Packit 423ecb
    void *context = NULL;
Packit 423ecb
    char *unescaped = NULL;
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
    int is_file_uri = 1;
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if (xmlOutputCallbackInitialized == 0)
Packit 423ecb
	xmlRegisterDefaultOutputCallbacks();
Packit 423ecb
Packit 423ecb
    if (URI == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    puri = xmlParseURI(URI);
Packit 423ecb
    if (puri != NULL) {
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
        if ((puri->scheme != NULL) &&
Packit 423ecb
	    (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
Packit 423ecb
	    is_file_uri = 0;
Packit 423ecb
#endif
Packit 423ecb
	/*
Packit 423ecb
	 * try to limit the damages of the URI unescaping code.
Packit 423ecb
	 */
Packit 423ecb
	if ((puri->scheme == NULL) ||
Packit 423ecb
	    (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
Packit 423ecb
	    unescaped = xmlURIUnescapeString(URI, 0, NULL);
Packit 423ecb
	xmlFreeURI(puri);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Try to find one of the output accept method accepting that scheme
Packit 423ecb
     * Go in reverse to give precedence to user defined handlers.
Packit 423ecb
     * try with an unescaped version of the URI
Packit 423ecb
     */
Packit 423ecb
    if (unescaped != NULL) {
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
Packit 423ecb
	    context = xmlGzfileOpenW(unescaped, compression);
Packit 423ecb
	    if (context != NULL) {
Packit 423ecb
		ret = xmlAllocOutputBufferInternal(encoder);
Packit 423ecb
		if (ret != NULL) {
Packit 423ecb
		    ret->context = context;
Packit 423ecb
		    ret->writecallback = xmlGzfileWrite;
Packit 423ecb
		    ret->closecallback = xmlGzfileClose;
Packit 423ecb
		}
Packit 423ecb
		xmlFree(unescaped);
Packit 423ecb
		return(ret);
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
#endif
Packit 423ecb
	for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
Packit 423ecb
	    if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
Packit 423ecb
		(xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
Packit 423ecb
#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
Packit 423ecb
		/*  Need to pass compression parameter into HTTP open calls  */
Packit 423ecb
		if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
Packit 423ecb
		    context = xmlIOHTTPOpenW(unescaped, compression);
Packit 423ecb
		else
Packit 423ecb
#endif
Packit 423ecb
		    context = xmlOutputCallbackTable[i].opencallback(unescaped);
Packit 423ecb
		if (context != NULL)
Packit 423ecb
		    break;
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
	xmlFree(unescaped);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * If this failed try with a non-escaped URI this may be a strange
Packit 423ecb
     * filename
Packit 423ecb
     */
Packit 423ecb
    if (context == NULL) {
Packit 423ecb
#ifdef HAVE_ZLIB_H
Packit 423ecb
	if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
Packit 423ecb
	    context = xmlGzfileOpenW(URI, compression);
Packit 423ecb
	    if (context != NULL) {
Packit 423ecb
		ret = xmlAllocOutputBufferInternal(encoder);
Packit 423ecb
		if (ret != NULL) {
Packit 423ecb
		    ret->context = context;
Packit 423ecb
		    ret->writecallback = xmlGzfileWrite;
Packit 423ecb
		    ret->closecallback = xmlGzfileClose;
Packit 423ecb
		}
Packit 423ecb
		return(ret);
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
#endif
Packit 423ecb
	for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
Packit 423ecb
	    if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
Packit 423ecb
		(xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
Packit 423ecb
#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
Packit 423ecb
		/*  Need to pass compression parameter into HTTP open calls  */
Packit 423ecb
		if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
Packit 423ecb
		    context = xmlIOHTTPOpenW(URI, compression);
Packit 423ecb
		else
Packit 423ecb
#endif
Packit 423ecb
		    context = xmlOutputCallbackTable[i].opencallback(URI);
Packit 423ecb
		if (context != NULL)
Packit 423ecb
		    break;
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (context == NULL) {
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Allocate the Output buffer front-end.
Packit 423ecb
     */
Packit 423ecb
    ret = xmlAllocOutputBufferInternal(encoder);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
	ret->context = context;
Packit 423ecb
	ret->writecallback = xmlOutputCallbackTable[i].writecallback;
Packit 423ecb
	ret->closecallback = xmlOutputCallbackTable[i].closecallback;
Packit 423ecb
    }
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferCreateFilename:
Packit 423ecb
 * @URI:  a C string containing the URI or filename
Packit 423ecb
 * @encoder:  the encoding converter or NULL
Packit 423ecb
 * @compression:  the compression ration (0 none, 9 max).
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered  output for the progressive saving of a file
Packit 423ecb
 * If filename is "-' then we use stdout as the output.
Packit 423ecb
 * Automatic support for ZLIB/Compress compressed document is provided
Packit 423ecb
 * by default if found at compile-time.
Packit 423ecb
 * TODO: currently if compression is set, the library only support
Packit 423ecb
 *       writing to a local file.
Packit 423ecb
 *
Packit 423ecb
 * Returns the new output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlOutputBufferCreateFilename(const char *URI,
Packit 423ecb
                              xmlCharEncodingHandlerPtr encoder,
Packit 423ecb
                              int compression ATTRIBUTE_UNUSED) {
Packit 423ecb
    if ((xmlOutputBufferCreateFilenameValue)) {
Packit 423ecb
		return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
Packit 423ecb
	}
Packit 423ecb
	return __xmlOutputBufferCreateFilename(URI, encoder, compression);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateFile:
Packit 423ecb
 * @file:  a FILE*
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for the progressive parsing of a FILE *
Packit 423ecb
 * buffered C I/O
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (xmlInputCallbackInitialized == 0)
Packit 423ecb
	xmlRegisterDefaultInputCallbacks();
Packit 423ecb
Packit 423ecb
    if (file == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocParserInputBuffer(enc);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = file;
Packit 423ecb
	ret->readcallback = xmlFileRead;
Packit 423ecb
	ret->closecallback = xmlFileFlush;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferCreateFile:
Packit 423ecb
 * @file:  a FILE*
Packit 423ecb
 * @encoder:  the encoding converter or NULL
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered output for the progressive saving to a FILE *
Packit 423ecb
 * buffered C I/O
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (xmlOutputCallbackInitialized == 0)
Packit 423ecb
	xmlRegisterDefaultOutputCallbacks();
Packit 423ecb
Packit 423ecb
    if (file == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocOutputBufferInternal(encoder);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = file;
Packit 423ecb
	ret->writecallback = xmlFileWrite;
Packit 423ecb
	ret->closecallback = xmlFileFlush;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferCreateBuffer:
Packit 423ecb
 * @buffer:  a xmlBufferPtr
Packit 423ecb
 * @encoder:  the encoding converter or NULL
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered output for the progressive saving to a xmlBuffer
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
Packit 423ecb
                            xmlCharEncodingHandlerPtr encoder) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (buffer == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
Packit 423ecb
                                  xmlBufferWrite,
Packit 423ecb
                                  (xmlOutputCloseCallback)
Packit 423ecb
                                  NULL, (void *) buffer, encoder);
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferGetContent:
Packit 423ecb
 * @out:  an xmlOutputBufferPtr
Packit 423ecb
 *
Packit 423ecb
 * Gives a pointer to the data currently held in the output buffer
Packit 423ecb
 *
Packit 423ecb
 * Returns a pointer to the data or NULL in case of error
Packit 423ecb
 */
Packit 423ecb
const xmlChar *
Packit 423ecb
xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
Packit 423ecb
    if ((out == NULL) || (out->buffer == NULL))
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
    return(xmlBufContent(out->buffer));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferGetSize:
Packit 423ecb
 * @out:  an xmlOutputBufferPtr
Packit 423ecb
 *
Packit 423ecb
 * Gives the length of the data currently held in the output buffer
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case or error or no data is held, the size otherwise
Packit 423ecb
 */
Packit 423ecb
size_t
Packit 423ecb
xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
Packit 423ecb
    if ((out == NULL) || (out->buffer == NULL))
Packit 423ecb
        return(0);
Packit 423ecb
Packit 423ecb
    return(xmlBufUse(out->buffer));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateFd:
Packit 423ecb
 * @fd:  a file descriptor number
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for the progressive parsing for the input
Packit 423ecb
 * from a file descriptor
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (fd < 0) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocParserInputBuffer(enc);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = (void *) (ptrdiff_t) fd;
Packit 423ecb
	ret->readcallback = xmlFdRead;
Packit 423ecb
	ret->closecallback = xmlFdClose;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateMem:
Packit 423ecb
 * @mem:  the memory input
Packit 423ecb
 * @size:  the length of the memory block
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for the progressive parsing for the input
Packit 423ecb
 * from a memory area.
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
    int errcode;
Packit 423ecb
Packit 423ecb
    if (size < 0) return(NULL);
Packit 423ecb
    if (mem == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocParserInputBuffer(enc);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = (void *) mem;
Packit 423ecb
	ret->readcallback = (xmlInputReadCallback) xmlNop;
Packit 423ecb
	ret->closecallback = NULL;
Packit 423ecb
	errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
Packit 423ecb
	if (errcode != 0) {
Packit 423ecb
	    xmlFree(ret);
Packit 423ecb
	    return(NULL);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateStatic:
Packit 423ecb
 * @mem:  the memory input
Packit 423ecb
 * @size:  the length of the memory block
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for the progressive parsing for the input
Packit 423ecb
 * from an immutable memory area. This will not copy the memory area to
Packit 423ecb
 * the buffer, but the memory is expected to be available until the end of
Packit 423ecb
 * the parsing, this is useful for example when using mmap'ed file.
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlParserInputBufferCreateStatic(const char *mem, int size,
Packit 423ecb
                                 xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (size < 0) return(NULL);
Packit 423ecb
    if (mem == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
	xmlIOErrMemory("creating input buffer");
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
    memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
Packit 423ecb
    ret->buffer = xmlBufCreateStatic((void *)mem, (size_t) size);
Packit 423ecb
    if (ret->buffer == NULL) {
Packit 423ecb
        xmlFree(ret);
Packit 423ecb
	return(NULL);
Packit 423ecb
    }
Packit 423ecb
    ret->encoder = xmlGetCharEncodingHandler(enc);
Packit 423ecb
    if (ret->encoder != NULL)
Packit 423ecb
        ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
Packit 423ecb
    else
Packit 423ecb
        ret->raw = NULL;
Packit 423ecb
    ret->compressed = -1;
Packit 423ecb
    ret->context = (void *) mem;
Packit 423ecb
    ret->readcallback = NULL;
Packit 423ecb
    ret->closecallback = NULL;
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferCreateFd:
Packit 423ecb
 * @fd:  a file descriptor number
Packit 423ecb
 * @encoder:  the encoding converter or NULL
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered output for the progressive saving
Packit 423ecb
 * to a file descriptor
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (fd < 0) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocOutputBufferInternal(encoder);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = (void *) (ptrdiff_t) fd;
Packit 423ecb
	ret->writecallback = xmlFdWrite;
Packit 423ecb
	ret->closecallback = NULL;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateIO:
Packit 423ecb
 * @ioread:  an I/O read function
Packit 423ecb
 * @ioclose:  an I/O close function
Packit 423ecb
 * @ioctx:  an I/O handler
Packit 423ecb
 * @enc:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered parser input for the progressive parsing for the input
Packit 423ecb
 * from an I/O handler
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser input or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferPtr
Packit 423ecb
xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
Packit 423ecb
	 xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
Packit 423ecb
    xmlParserInputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (ioread == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocParserInputBuffer(enc);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = (void *) ioctx;
Packit 423ecb
	ret->readcallback = ioread;
Packit 423ecb
	ret->closecallback = ioclose;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferCreateIO:
Packit 423ecb
 * @iowrite:  an I/O write function
Packit 423ecb
 * @ioclose:  an I/O close function
Packit 423ecb
 * @ioctx:  an I/O handler
Packit 423ecb
 * @encoder:  the charset encoding if known
Packit 423ecb
 *
Packit 423ecb
 * Create a buffered output for the progressive saving
Packit 423ecb
 * to an I/O handler
Packit 423ecb
 *
Packit 423ecb
 * Returns the new parser output or NULL
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferPtr
Packit 423ecb
xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
Packit 423ecb
	 xmlOutputCloseCallback  ioclose, void *ioctx,
Packit 423ecb
	 xmlCharEncodingHandlerPtr encoder) {
Packit 423ecb
    xmlOutputBufferPtr ret;
Packit 423ecb
Packit 423ecb
    if (iowrite == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
    ret = xmlAllocOutputBufferInternal(encoder);
Packit 423ecb
    if (ret != NULL) {
Packit 423ecb
        ret->context = (void *) ioctx;
Packit 423ecb
	ret->writecallback = iowrite;
Packit 423ecb
	ret->closecallback = ioclose;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferCreateFilenameDefault:
Packit 423ecb
 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
Packit 423ecb
 *
Packit 423ecb
 * Registers a callback for URI input file handling
Packit 423ecb
 *
Packit 423ecb
 * Returns the old value of the registration function
Packit 423ecb
 */
Packit 423ecb
xmlParserInputBufferCreateFilenameFunc
Packit 423ecb
xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
Packit 423ecb
{
Packit 423ecb
    xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
Packit 423ecb
    if (old == NULL) {
Packit 423ecb
		old = __xmlParserInputBufferCreateFilename;
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
    xmlParserInputBufferCreateFilenameValue = func;
Packit 423ecb
    return(old);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferCreateFilenameDefault:
Packit 423ecb
 * @func: function pointer to the new OutputBufferCreateFilenameFunc
Packit 423ecb
 *
Packit 423ecb
 * Registers a callback for URI output file handling
Packit 423ecb
 *
Packit 423ecb
 * Returns the old value of the registration function
Packit 423ecb
 */
Packit 423ecb
xmlOutputBufferCreateFilenameFunc
Packit 423ecb
xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
Packit 423ecb
{
Packit 423ecb
    xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
    if (old == NULL) {
Packit 423ecb
		old = __xmlOutputBufferCreateFilename;
Packit 423ecb
	}
Packit 423ecb
#endif
Packit 423ecb
    xmlOutputBufferCreateFilenameValue = func;
Packit 423ecb
    return(old);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferPush:
Packit 423ecb
 * @in:  a buffered parser input
Packit 423ecb
 * @len:  the size in bytes of the array.
Packit 423ecb
 * @buf:  an char array
Packit 423ecb
 *
Packit 423ecb
 * Push the content of the arry in the input buffer
Packit 423ecb
 * This routine handle the I18N transcoding to internal UTF-8
Packit 423ecb
 * This is used when operating the parser in progressive (push) mode.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of chars read and stored in the buffer, or -1
Packit 423ecb
 *         in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlParserInputBufferPush(xmlParserInputBufferPtr in,
Packit 423ecb
	                 int len, const char *buf) {
Packit 423ecb
    int nbchars = 0;
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    if (len < 0) return(0);
Packit 423ecb
    if ((in == NULL) || (in->error)) return(-1);
Packit 423ecb
    if (in->encoder != NULL) {
Packit 423ecb
        unsigned int use;
Packit 423ecb
Packit 423ecb
        /*
Packit 423ecb
	 * Store the data in the incoming raw buffer
Packit 423ecb
	 */
Packit 423ecb
        if (in->raw == NULL) {
Packit 423ecb
	    in->raw = xmlBufCreate();
Packit 423ecb
	}
Packit 423ecb
	ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
Packit 423ecb
	if (ret != 0)
Packit 423ecb
	    return(-1);
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * convert as much as possible to the parser reading buffer.
Packit 423ecb
	 */
Packit 423ecb
	use = xmlBufUse(in->raw);
Packit 423ecb
	nbchars = xmlCharEncInput(in, 1);
Packit 423ecb
	if (nbchars < 0) {
Packit 423ecb
	    xmlIOErr(XML_IO_ENCODER, NULL);
Packit 423ecb
	    in->error = XML_IO_ENCODER;
Packit 423ecb
	    return(-1);
Packit 423ecb
	}
Packit 423ecb
	in->rawconsumed += (use - xmlBufUse(in->raw));
Packit 423ecb
    } else {
Packit 423ecb
	nbchars = len;
Packit 423ecb
        ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
Packit 423ecb
	if (ret != 0)
Packit 423ecb
	    return(-1);
Packit 423ecb
    }
Packit 423ecb
#ifdef DEBUG_INPUT
Packit 423ecb
    xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
	    "I/O: pushed %d chars, buffer %d/%d\n",
Packit 423ecb
            nbchars, xmlBufUse(in->buffer), xmlBufLength(in->buffer));
Packit 423ecb
#endif
Packit 423ecb
    return(nbchars);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * endOfInput:
Packit 423ecb
 *
Packit 423ecb
 * When reading from an Input channel indicated end of file or error
Packit 423ecb
 * don't reread from it again.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
endOfInput (void * context ATTRIBUTE_UNUSED,
Packit 423ecb
	    char * buffer ATTRIBUTE_UNUSED,
Packit 423ecb
	    int len ATTRIBUTE_UNUSED) {
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferGrow:
Packit 423ecb
 * @in:  a buffered parser input
Packit 423ecb
 * @len:  indicative value of the amount of chars to read
Packit 423ecb
 *
Packit 423ecb
 * Grow up the content of the input buffer, the old data are preserved
Packit 423ecb
 * This routine handle the I18N transcoding to internal UTF-8
Packit 423ecb
 * This routine is used when operating the parser in normal (pull) mode
Packit 423ecb
 *
Packit 423ecb
 * TODO: one should be able to remove one extra copy by copying directly
Packit 423ecb
 *       onto in->buffer or in->raw
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of chars read and stored in the buffer, or -1
Packit 423ecb
 *         in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
Packit 423ecb
    char *buffer = NULL;
Packit 423ecb
    int res = 0;
Packit 423ecb
    int nbchars = 0;
Packit 423ecb
Packit 423ecb
    if ((in == NULL) || (in->error)) return(-1);
Packit 423ecb
    if ((len <= MINLEN) && (len != 4))
Packit 423ecb
        len = MINLEN;
Packit 423ecb
Packit 423ecb
    if (xmlBufAvail(in->buffer) <= 0) {
Packit 423ecb
	xmlIOErr(XML_IO_BUFFER_FULL, NULL);
Packit 423ecb
	in->error = XML_IO_BUFFER_FULL;
Packit 423ecb
	return(-1);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (xmlBufGrow(in->buffer, len + 1) < 0) {
Packit 423ecb
        xmlIOErrMemory("growing input buffer");
Packit 423ecb
        in->error = XML_ERR_NO_MEMORY;
Packit 423ecb
        return(-1);
Packit 423ecb
    }
Packit 423ecb
    buffer = (char *)xmlBufEnd(in->buffer);
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Call the read method for this I/O type.
Packit 423ecb
     */
Packit 423ecb
    if (in->readcallback != NULL) {
Packit 423ecb
	res = in->readcallback(in->context, &buffer[0], len);
Packit 423ecb
	if (res <= 0)
Packit 423ecb
	    in->readcallback = endOfInput;
Packit 423ecb
    } else {
Packit 423ecb
	xmlIOErr(XML_IO_NO_INPUT, NULL);
Packit 423ecb
	in->error = XML_IO_NO_INPUT;
Packit 423ecb
	return(-1);
Packit 423ecb
    }
Packit 423ecb
    if (res < 0) {
Packit 423ecb
	return(-1);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * try to establish compressed status of input if not done already
Packit 423ecb
     */
Packit 423ecb
    if (in->compressed == -1) {
Packit 423ecb
#ifdef LIBXML_LZMA_ENABLED
Packit 423ecb
	if (in->readcallback == xmlXzfileRead)
Packit 423ecb
            in->compressed = __libxml2_xzcompressed(in->context);
Packit 423ecb
#endif
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    len = res;
Packit 423ecb
    if (in->encoder != NULL) {
Packit 423ecb
        unsigned int use;
Packit 423ecb
Packit 423ecb
        /*
Packit 423ecb
	 * Store the data in the incoming raw buffer
Packit 423ecb
	 */
Packit 423ecb
        if (in->raw == NULL) {
Packit 423ecb
	    in->raw = xmlBufCreate();
Packit 423ecb
	}
Packit 423ecb
	res = xmlBufAdd(in->raw, (const xmlChar *) buffer, len);
Packit 423ecb
	if (res != 0)
Packit 423ecb
	    return(-1);
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * convert as much as possible to the parser reading buffer.
Packit 423ecb
	 */
Packit 423ecb
	use = xmlBufUse(in->raw);
Packit 423ecb
	nbchars = xmlCharEncInput(in, 1);
Packit 423ecb
	if (nbchars < 0) {
Packit 423ecb
	    xmlIOErr(XML_IO_ENCODER, NULL);
Packit 423ecb
	    in->error = XML_IO_ENCODER;
Packit 423ecb
	    return(-1);
Packit 423ecb
	}
Packit 423ecb
	in->rawconsumed += (use - xmlBufUse(in->raw));
Packit 423ecb
    } else {
Packit 423ecb
	nbchars = len;
Packit 423ecb
        xmlBufAddLen(in->buffer, nbchars);
Packit 423ecb
    }
Packit 423ecb
#ifdef DEBUG_INPUT
Packit 423ecb
    xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
	    "I/O: read %d chars, buffer %d\n",
Packit 423ecb
            nbchars, xmlBufUse(in->buffer));
Packit 423ecb
#endif
Packit 423ecb
    return(nbchars);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserInputBufferRead:
Packit 423ecb
 * @in:  a buffered parser input
Packit 423ecb
 * @len:  indicative value of the amount of chars to read
Packit 423ecb
 *
Packit 423ecb
 * Refresh the content of the input buffer, the old data are considered
Packit 423ecb
 * consumed
Packit 423ecb
 * This routine handle the I18N transcoding to internal UTF-8
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of chars read and stored in the buffer, or -1
Packit 423ecb
 *         in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
Packit 423ecb
    if ((in == NULL) || (in->error)) return(-1);
Packit 423ecb
    if (in->readcallback != NULL)
Packit 423ecb
	return(xmlParserInputBufferGrow(in, len));
Packit 423ecb
    else if (xmlBufGetAllocationScheme(in->buffer) == XML_BUFFER_ALLOC_IMMUTABLE)
Packit 423ecb
	return(0);
Packit 423ecb
    else
Packit 423ecb
        return(-1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_OUTPUT_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferWrite:
Packit 423ecb
 * @out:  a buffered parser output
Packit 423ecb
 * @len:  the size in bytes of the array.
Packit 423ecb
 * @buf:  an char array
Packit 423ecb
 *
Packit 423ecb
 * Write the content of the array in the output I/O buffer
Packit 423ecb
 * This routine handle the I18N transcoding from internal UTF-8
Packit 423ecb
 * The buffer is lossless, i.e. will store in case of partial
Packit 423ecb
 * or delayed writes.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of chars immediately written, or -1
Packit 423ecb
 *         in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
Packit 423ecb
    int nbchars = 0; /* number of chars to output to I/O */
Packit 423ecb
    int ret;         /* return from function call */
Packit 423ecb
    int written = 0; /* number of char written to I/O so far */
Packit 423ecb
    int chunk;       /* number of byte curreent processed from buf */
Packit 423ecb
Packit 423ecb
    if ((out == NULL) || (out->error)) return(-1);
Packit 423ecb
    if (len < 0) return(0);
Packit 423ecb
    if (out->error) return(-1);
Packit 423ecb
Packit 423ecb
    do {
Packit 423ecb
	chunk = len;
Packit 423ecb
	if (chunk > 4 * MINLEN)
Packit 423ecb
	    chunk = 4 * MINLEN;
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * first handle encoding stuff.
Packit 423ecb
	 */
Packit 423ecb
	if (out->encoder != NULL) {
Packit 423ecb
	    /*
Packit 423ecb
	     * Store the data in the incoming raw buffer
Packit 423ecb
	     */
Packit 423ecb
	    if (out->conv == NULL) {
Packit 423ecb
		out->conv = xmlBufCreate();
Packit 423ecb
	    }
Packit 423ecb
	    ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
Packit 423ecb
	    if (ret != 0)
Packit 423ecb
	        return(-1);
Packit 423ecb
Packit 423ecb
	    if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len))
Packit 423ecb
		goto done;
Packit 423ecb
Packit 423ecb
	    /*
Packit 423ecb
	     * convert as much as possible to the parser reading buffer.
Packit 423ecb
	     */
Packit 423ecb
	    ret = xmlCharEncOutput(out, 0);
Packit 423ecb
	    if ((ret < 0) && (ret != -3)) {
Packit 423ecb
		xmlIOErr(XML_IO_ENCODER, NULL);
Packit 423ecb
		out->error = XML_IO_ENCODER;
Packit 423ecb
		return(-1);
Packit 423ecb
	    }
Packit 423ecb
	    nbchars = xmlBufUse(out->conv);
Packit 423ecb
	} else {
Packit 423ecb
	    ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
Packit 423ecb
	    if (ret != 0)
Packit 423ecb
	        return(-1);
Packit 423ecb
	    nbchars = xmlBufUse(out->buffer);
Packit 423ecb
	}
Packit 423ecb
	buf += chunk;
Packit 423ecb
	len -= chunk;
Packit 423ecb
Packit 423ecb
	if ((nbchars < MINLEN) && (len <= 0))
Packit 423ecb
	    goto done;
Packit 423ecb
Packit 423ecb
	if (out->writecallback) {
Packit 423ecb
	    /*
Packit 423ecb
	     * second write the stuff to the I/O channel
Packit 423ecb
	     */
Packit 423ecb
	    if (out->encoder != NULL) {
Packit 423ecb
		ret = out->writecallback(out->context,
Packit 423ecb
                           (const char *)xmlBufContent(out->conv), nbchars);
Packit 423ecb
		if (ret >= 0)
Packit 423ecb
		    xmlBufShrink(out->conv, ret);
Packit 423ecb
	    } else {
Packit 423ecb
		ret = out->writecallback(out->context,
Packit 423ecb
                           (const char *)xmlBufContent(out->buffer), nbchars);
Packit 423ecb
		if (ret >= 0)
Packit 423ecb
		    xmlBufShrink(out->buffer, ret);
Packit 423ecb
	    }
Packit 423ecb
	    if (ret < 0) {
Packit 423ecb
		xmlIOErr(XML_IO_WRITE, NULL);
Packit 423ecb
		out->error = XML_IO_WRITE;
Packit 423ecb
		return(ret);
Packit 423ecb
	    }
Packit 423ecb
	    out->written += ret;
Packit 423ecb
	}
Packit 423ecb
	written += nbchars;
Packit 423ecb
    } while (len > 0);
Packit 423ecb
Packit 423ecb
done:
Packit 423ecb
#ifdef DEBUG_INPUT
Packit 423ecb
    xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
	    "I/O: wrote %d chars\n", written);
Packit 423ecb
#endif
Packit 423ecb
    return(written);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlEscapeContent:
Packit 423ecb
 * @out:  a pointer to an array of bytes to store the result
Packit 423ecb
 * @outlen:  the length of @out
Packit 423ecb
 * @in:  a pointer to an array of unescaped UTF-8 bytes
Packit 423ecb
 * @inlen:  the length of @in
Packit 423ecb
 *
Packit 423ecb
 * Take a block of UTF-8 chars in and escape them.
Packit 423ecb
 * Returns 0 if success, or -1 otherwise
Packit 423ecb
 * The value of @inlen after return is the number of octets consumed
Packit 423ecb
 *     if the return value is positive, else unpredictable.
Packit 423ecb
 * The value of @outlen after return is the number of octets consumed.
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
xmlEscapeContent(unsigned char* out, int *outlen,
Packit 423ecb
                 const xmlChar* in, int *inlen) {
Packit 423ecb
    unsigned char* outstart = out;
Packit 423ecb
    const unsigned char* base = in;
Packit 423ecb
    unsigned char* outend = out + *outlen;
Packit 423ecb
    const unsigned char* inend;
Packit 423ecb
Packit 423ecb
    inend = in + (*inlen);
Packit 423ecb
Packit 423ecb
    while ((in < inend) && (out < outend)) {
Packit 423ecb
	if (*in == '<') {
Packit 423ecb
	    if (outend - out < 4) break;
Packit 423ecb
	    *out++ = '&';
Packit 423ecb
	    *out++ = 'l';
Packit 423ecb
	    *out++ = 't';
Packit 423ecb
	    *out++ = ';';
Packit 423ecb
	} else if (*in == '>') {
Packit 423ecb
	    if (outend - out < 4) break;
Packit 423ecb
	    *out++ = '&';
Packit 423ecb
	    *out++ = 'g';
Packit 423ecb
	    *out++ = 't';
Packit 423ecb
	    *out++ = ';';
Packit 423ecb
	} else if (*in == '&') {
Packit 423ecb
	    if (outend - out < 5) break;
Packit 423ecb
	    *out++ = '&';
Packit 423ecb
	    *out++ = 'a';
Packit 423ecb
	    *out++ = 'm';
Packit 423ecb
	    *out++ = 'p';
Packit 423ecb
	    *out++ = ';';
Packit 423ecb
	} else if (*in == '\r') {
Packit 423ecb
	    if (outend - out < 5) break;
Packit 423ecb
	    *out++ = '&';
Packit 423ecb
	    *out++ = '#';
Packit 423ecb
	    *out++ = '1';
Packit 423ecb
	    *out++ = '3';
Packit 423ecb
	    *out++ = ';';
Packit 423ecb
	} else {
Packit 423ecb
	    *out++ = (unsigned char) *in;
Packit 423ecb
	}
Packit 423ecb
	++in;
Packit 423ecb
    }
Packit 423ecb
    *outlen = out - outstart;
Packit 423ecb
    *inlen = in - base;
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferWriteEscape:
Packit 423ecb
 * @out:  a buffered parser output
Packit 423ecb
 * @str:  a zero terminated UTF-8 string
Packit 423ecb
 * @escaping:  an optional escaping function (or NULL)
Packit 423ecb
 *
Packit 423ecb
 * Write the content of the string in the output I/O buffer
Packit 423ecb
 * This routine escapes the caracters and then handle the I18N
Packit 423ecb
 * transcoding from internal UTF-8
Packit 423ecb
 * The buffer is lossless, i.e. will store in case of partial
Packit 423ecb
 * or delayed writes.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of chars immediately written, or -1
Packit 423ecb
 *         in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
Packit 423ecb
                           xmlCharEncodingOutputFunc escaping) {
Packit 423ecb
    int nbchars = 0; /* number of chars to output to I/O */
Packit 423ecb
    int ret;         /* return from function call */
Packit 423ecb
    int written = 0; /* number of char written to I/O so far */
Packit 423ecb
    int oldwritten=0;/* loop guard */
Packit 423ecb
    int chunk;       /* number of byte currently processed from str */
Packit 423ecb
    int len;         /* number of bytes in str */
Packit 423ecb
    int cons;        /* byte from str consumed */
Packit 423ecb
Packit 423ecb
    if ((out == NULL) || (out->error) || (str == NULL) ||
Packit 423ecb
        (out->buffer == NULL) ||
Packit 423ecb
	(xmlBufGetAllocationScheme(out->buffer) == XML_BUFFER_ALLOC_IMMUTABLE))
Packit 423ecb
        return(-1);
Packit 423ecb
    len = strlen((const char *)str);
Packit 423ecb
    if (len < 0) return(0);
Packit 423ecb
    if (out->error) return(-1);
Packit 423ecb
    if (escaping == NULL) escaping = xmlEscapeContent;
Packit 423ecb
Packit 423ecb
    do {
Packit 423ecb
        oldwritten = written;
Packit 423ecb
Packit 423ecb
        /*
Packit 423ecb
	 * how many bytes to consume and how many bytes to store.
Packit 423ecb
	 */
Packit 423ecb
	cons = len;
Packit 423ecb
	chunk = xmlBufAvail(out->buffer) - 1;
Packit 423ecb
Packit 423ecb
        /*
Packit 423ecb
	 * make sure we have enough room to save first, if this is
Packit 423ecb
	 * not the case force a flush, but make sure we stay in the loop
Packit 423ecb
	 */
Packit 423ecb
	if (chunk < 40) {
Packit 423ecb
	    if (xmlBufGrow(out->buffer, 100) < 0)
Packit 423ecb
	        return(-1);
Packit 423ecb
            oldwritten = -1;
Packit 423ecb
	    continue;
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * first handle encoding stuff.
Packit 423ecb
	 */
Packit 423ecb
	if (out->encoder != NULL) {
Packit 423ecb
	    /*
Packit 423ecb
	     * Store the data in the incoming raw buffer
Packit 423ecb
	     */
Packit 423ecb
	    if (out->conv == NULL) {
Packit 423ecb
		out->conv = xmlBufCreate();
Packit 423ecb
	    }
Packit 423ecb
	    ret = escaping(xmlBufEnd(out->buffer) ,
Packit 423ecb
	                   &chunk, str, &cons;;
Packit 423ecb
	    if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
Packit 423ecb
	        return(-1);
Packit 423ecb
            xmlBufAddLen(out->buffer, chunk);
Packit 423ecb
Packit 423ecb
	    if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
Packit 423ecb
		goto done;
Packit 423ecb
Packit 423ecb
	    /*
Packit 423ecb
	     * convert as much as possible to the output buffer.
Packit 423ecb
	     */
Packit 423ecb
	    ret = xmlCharEncOutput(out, 0);
Packit 423ecb
	    if ((ret < 0) && (ret != -3)) {
Packit 423ecb
		xmlIOErr(XML_IO_ENCODER, NULL);
Packit 423ecb
		out->error = XML_IO_ENCODER;
Packit 423ecb
		return(-1);
Packit 423ecb
	    }
Packit 423ecb
	    nbchars = xmlBufUse(out->conv);
Packit 423ecb
	} else {
Packit 423ecb
	    ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons;;
Packit 423ecb
	    if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
Packit 423ecb
	        return(-1);
Packit 423ecb
            xmlBufAddLen(out->buffer, chunk);
Packit 423ecb
	    nbchars = xmlBufUse(out->buffer);
Packit 423ecb
	}
Packit 423ecb
	str += cons;
Packit 423ecb
	len -= cons;
Packit 423ecb
Packit 423ecb
	if ((nbchars < MINLEN) && (len <= 0))
Packit 423ecb
	    goto done;
Packit 423ecb
Packit 423ecb
	if (out->writecallback) {
Packit 423ecb
	    /*
Packit 423ecb
	     * second write the stuff to the I/O channel
Packit 423ecb
	     */
Packit 423ecb
	    if (out->encoder != NULL) {
Packit 423ecb
		ret = out->writecallback(out->context,
Packit 423ecb
                           (const char *)xmlBufContent(out->conv), nbchars);
Packit 423ecb
		if (ret >= 0)
Packit 423ecb
		    xmlBufShrink(out->conv, ret);
Packit 423ecb
	    } else {
Packit 423ecb
		ret = out->writecallback(out->context,
Packit 423ecb
                           (const char *)xmlBufContent(out->buffer), nbchars);
Packit 423ecb
		if (ret >= 0)
Packit 423ecb
		    xmlBufShrink(out->buffer, ret);
Packit 423ecb
	    }
Packit 423ecb
	    if (ret < 0) {
Packit 423ecb
		xmlIOErr(XML_IO_WRITE, NULL);
Packit 423ecb
		out->error = XML_IO_WRITE;
Packit 423ecb
		return(ret);
Packit 423ecb
	    }
Packit 423ecb
	    out->written += ret;
Packit 423ecb
	} else if (xmlBufAvail(out->buffer) < MINLEN) {
Packit 423ecb
	    xmlBufGrow(out->buffer, MINLEN);
Packit 423ecb
	}
Packit 423ecb
	written += nbchars;
Packit 423ecb
    } while ((len > 0) && (oldwritten != written));
Packit 423ecb
Packit 423ecb
done:
Packit 423ecb
#ifdef DEBUG_INPUT
Packit 423ecb
    xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
	    "I/O: wrote %d chars\n", written);
Packit 423ecb
#endif
Packit 423ecb
    return(written);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferWriteString:
Packit 423ecb
 * @out:  a buffered parser output
Packit 423ecb
 * @str:  a zero terminated C string
Packit 423ecb
 *
Packit 423ecb
 * Write the content of the string in the output I/O buffer
Packit 423ecb
 * This routine handle the I18N transcoding from internal UTF-8
Packit 423ecb
 * The buffer is lossless, i.e. will store in case of partial
Packit 423ecb
 * or delayed writes.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of chars immediately written, or -1
Packit 423ecb
 *         in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
Packit 423ecb
    int len;
Packit 423ecb
Packit 423ecb
    if ((out == NULL) || (out->error)) return(-1);
Packit 423ecb
    if (str == NULL)
Packit 423ecb
        return(-1);
Packit 423ecb
    len = strlen(str);
Packit 423ecb
Packit 423ecb
    if (len > 0)
Packit 423ecb
	return(xmlOutputBufferWrite(out, len, str));
Packit 423ecb
    return(len);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlOutputBufferFlush:
Packit 423ecb
 * @out:  a buffered output
Packit 423ecb
 *
Packit 423ecb
 * flushes the output I/O channel
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of byte written or -1 in case of error.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlOutputBufferFlush(xmlOutputBufferPtr out) {
Packit 423ecb
    int nbchars = 0, ret = 0;
Packit 423ecb
Packit 423ecb
    if ((out == NULL) || (out->error)) return(-1);
Packit 423ecb
    /*
Packit 423ecb
     * first handle encoding stuff.
Packit 423ecb
     */
Packit 423ecb
    if ((out->conv != NULL) && (out->encoder != NULL)) {
Packit 423ecb
	/*
Packit 423ecb
	 * convert as much as possible to the parser output buffer.
Packit 423ecb
	 */
Packit 423ecb
	do {
Packit 423ecb
	    nbchars = xmlCharEncOutput(out, 0);
Packit 423ecb
	    if (nbchars < 0) {
Packit 423ecb
		xmlIOErr(XML_IO_ENCODER, NULL);
Packit 423ecb
		out->error = XML_IO_ENCODER;
Packit 423ecb
		return(-1);
Packit 423ecb
	    }
Packit 423ecb
	} while (nbchars);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * second flush the stuff to the I/O channel
Packit 423ecb
     */
Packit 423ecb
    if ((out->conv != NULL) && (out->encoder != NULL) &&
Packit 423ecb
	(out->writecallback != NULL)) {
Packit 423ecb
	ret = out->writecallback(out->context,
Packit 423ecb
                                 (const char *)xmlBufContent(out->conv),
Packit 423ecb
                                 xmlBufUse(out->conv));
Packit 423ecb
	if (ret >= 0)
Packit 423ecb
	    xmlBufShrink(out->conv, ret);
Packit 423ecb
    } else if (out->writecallback != NULL) {
Packit 423ecb
	ret = out->writecallback(out->context,
Packit 423ecb
                                 (const char *)xmlBufContent(out->buffer),
Packit 423ecb
                                 xmlBufUse(out->buffer));
Packit 423ecb
	if (ret >= 0)
Packit 423ecb
	    xmlBufShrink(out->buffer, ret);
Packit 423ecb
    }
Packit 423ecb
    if (ret < 0) {
Packit 423ecb
	xmlIOErr(XML_IO_FLUSH, NULL);
Packit 423ecb
	out->error = XML_IO_FLUSH;
Packit 423ecb
	return(ret);
Packit 423ecb
    }
Packit 423ecb
    out->written += ret;
Packit 423ecb
Packit 423ecb
#ifdef DEBUG_INPUT
Packit 423ecb
    xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
	    "I/O: flushed %d chars\n", ret);
Packit 423ecb
#endif
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_OUTPUT_ENABLED */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserGetDirectory:
Packit 423ecb
 * @filename:  the path to a file
Packit 423ecb
 *
Packit 423ecb
 * lookup the directory for that file
Packit 423ecb
 *
Packit 423ecb
 * Returns a new allocated string containing the directory, or NULL.
Packit 423ecb
 */
Packit 423ecb
char *
Packit 423ecb
xmlParserGetDirectory(const char *filename) {
Packit 423ecb
    char *ret = NULL;
Packit 423ecb
    char dir[1024];
Packit 423ecb
    char *cur;
Packit 423ecb
Packit 423ecb
#ifdef _WIN32_WCE  /* easy way by now ... wince does not have dirs! */
Packit 423ecb
    return NULL;
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if (xmlInputCallbackInitialized == 0)
Packit 423ecb
	xmlRegisterDefaultInputCallbacks();
Packit 423ecb
Packit 423ecb
    if (filename == NULL) return(NULL);
Packit 423ecb
Packit 423ecb
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit 423ecb
#   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
Packit 423ecb
#else
Packit 423ecb
#   define IS_XMLPGD_SEP(ch) (ch=='/')
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    strncpy(dir, filename, 1023);
Packit 423ecb
    dir[1023] = 0;
Packit 423ecb
    cur = &dir[strlen(dir)];
Packit 423ecb
    while (cur > dir) {
Packit 423ecb
         if (IS_XMLPGD_SEP(*cur)) break;
Packit 423ecb
	 cur --;
Packit 423ecb
    }
Packit 423ecb
    if (IS_XMLPGD_SEP(*cur)) {
Packit 423ecb
        if (cur == dir) dir[1] = 0;
Packit 423ecb
	else *cur = 0;
Packit 423ecb
	ret = xmlMemStrdup(dir);
Packit 423ecb
    } else {
Packit 423ecb
        if (getcwd(dir, 1024) != NULL) {
Packit 423ecb
	    dir[1023] = 0;
Packit 423ecb
	    ret = xmlMemStrdup(dir);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    return(ret);
Packit 423ecb
#undef IS_XMLPGD_SEP
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/****************************************************************
Packit 423ecb
 *								*
Packit 423ecb
 *		External entities loading			*
Packit 423ecb
 *								*
Packit 423ecb
 ****************************************************************/
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCheckHTTPInput:
Packit 423ecb
 * @ctxt: an XML parser context
Packit 423ecb
 * @ret: an XML parser input
Packit 423ecb
 *
Packit 423ecb
 * Check an input in case it was created from an HTTP stream, in that
Packit 423ecb
 * case it will handle encoding and update of the base URL in case of
Packit 423ecb
 * redirection. It also checks for HTTP errors in which case the input
Packit 423ecb
 * is cleanly freed up and an appropriate error is raised in context
Packit 423ecb
 *
Packit 423ecb
 * Returns the input or NULL in case of HTTP error.
Packit 423ecb
 */
Packit 423ecb
xmlParserInputPtr
Packit 423ecb
xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
Packit 423ecb
#ifdef LIBXML_HTTP_ENABLED
Packit 423ecb
    if ((ret != NULL) && (ret->buf != NULL) &&
Packit 423ecb
        (ret->buf->readcallback == xmlIOHTTPRead) &&
Packit 423ecb
        (ret->buf->context != NULL)) {
Packit 423ecb
        const char *encoding;
Packit 423ecb
        const char *redir;
Packit 423ecb
        const char *mime;
Packit 423ecb
        int code;
Packit 423ecb
Packit 423ecb
        code = xmlNanoHTTPReturnCode(ret->buf->context);
Packit 423ecb
        if (code >= 400) {
Packit 423ecb
            /* fatal error */
Packit 423ecb
	    if (ret->filename != NULL)
Packit 423ecb
		__xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
Packit 423ecb
                         (const char *) ret->filename);
Packit 423ecb
	    else
Packit 423ecb
		__xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
Packit 423ecb
            xmlFreeInputStream(ret);
Packit 423ecb
            ret = NULL;
Packit 423ecb
        } else {
Packit 423ecb
Packit 423ecb
            mime = xmlNanoHTTPMimeType(ret->buf->context);
Packit 423ecb
            if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
Packit 423ecb
                (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
Packit 423ecb
                encoding = xmlNanoHTTPEncoding(ret->buf->context);
Packit 423ecb
                if (encoding != NULL) {
Packit 423ecb
                    xmlCharEncodingHandlerPtr handler;
Packit 423ecb
Packit 423ecb
                    handler = xmlFindCharEncodingHandler(encoding);
Packit 423ecb
                    if (handler != NULL) {
Packit 423ecb
                        xmlSwitchInputEncoding(ctxt, ret, handler);
Packit 423ecb
                    } else {
Packit 423ecb
                        __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
Packit 423ecb
                                         "Unknown encoding %s",
Packit 423ecb
                                         BAD_CAST encoding, NULL);
Packit 423ecb
                    }
Packit 423ecb
                    if (ret->encoding == NULL)
Packit 423ecb
                        ret->encoding = xmlStrdup(BAD_CAST encoding);
Packit 423ecb
                }
Packit 423ecb
#if 0
Packit 423ecb
            } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
Packit 423ecb
#endif
Packit 423ecb
            }
Packit 423ecb
            redir = xmlNanoHTTPRedir(ret->buf->context);
Packit 423ecb
            if (redir != NULL) {
Packit 423ecb
                if (ret->filename != NULL)
Packit 423ecb
                    xmlFree((xmlChar *) ret->filename);
Packit 423ecb
                if (ret->directory != NULL) {
Packit 423ecb
                    xmlFree((xmlChar *) ret->directory);
Packit 423ecb
                    ret->directory = NULL;
Packit 423ecb
                }
Packit 423ecb
                ret->filename =
Packit 423ecb
                    (char *) xmlStrdup((const xmlChar *) redir);
Packit 423ecb
            }
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
#endif
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static int xmlNoNetExists(const char *URL) {
Packit 423ecb
    const char *path;
Packit 423ecb
Packit 423ecb
    if (URL == NULL)
Packit 423ecb
	return(0);
Packit 423ecb
Packit 423ecb
    if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &URL[17];
Packit 423ecb
#else
Packit 423ecb
	path = &URL[16];
Packit 423ecb
#endif
Packit 423ecb
    else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
Packit 423ecb
#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
Packit 423ecb
	path = &URL[8];
Packit 423ecb
#else
Packit 423ecb
	path = &URL[7];
Packit 423ecb
#endif
Packit 423ecb
    } else
Packit 423ecb
	path = URL;
Packit 423ecb
Packit 423ecb
    return xmlCheckFilename(path);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_CATALOG_ENABLED
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlResolveResourceFromCatalog:
Packit 423ecb
 * @URL:  the URL for the entity to load
Packit 423ecb
 * @ID:  the System ID for the entity to load
Packit 423ecb
 * @ctxt:  the context in which the entity is called or NULL
Packit 423ecb
 *
Packit 423ecb
 * Resolves the URL and ID against the appropriate catalog.
Packit 423ecb
 * This function is used by xmlDefaultExternalEntityLoader and
Packit 423ecb
 * xmlNoNetExternalEntityLoader.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new allocated URL, or NULL.
Packit 423ecb
 */
Packit 423ecb
static xmlChar *
Packit 423ecb
xmlResolveResourceFromCatalog(const char *URL, const char *ID,
Packit 423ecb
                              xmlParserCtxtPtr ctxt) {
Packit 423ecb
    xmlChar *resource = NULL;
Packit 423ecb
    xmlCatalogAllow pref;
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * If the resource doesn't exists as a file,
Packit 423ecb
     * try to load it from the resource pointed in the catalogs
Packit 423ecb
     */
Packit 423ecb
    pref = xmlCatalogGetDefaults();
Packit 423ecb
Packit 423ecb
    if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
Packit 423ecb
	/*
Packit 423ecb
	 * Do a local lookup
Packit 423ecb
	 */
Packit 423ecb
	if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
Packit 423ecb
	    ((pref == XML_CATA_ALLOW_ALL) ||
Packit 423ecb
	     (pref == XML_CATA_ALLOW_DOCUMENT))) {
Packit 423ecb
	    resource = xmlCatalogLocalResolve(ctxt->catalogs,
Packit 423ecb
					      (const xmlChar *)ID,
Packit 423ecb
					      (const xmlChar *)URL);
Packit 423ecb
        }
Packit 423ecb
	/*
Packit 423ecb
	 * Try a global lookup
Packit 423ecb
	 */
Packit 423ecb
	if ((resource == NULL) &&
Packit 423ecb
	    ((pref == XML_CATA_ALLOW_ALL) ||
Packit 423ecb
	     (pref == XML_CATA_ALLOW_GLOBAL))) {
Packit 423ecb
	    resource = xmlCatalogResolve((const xmlChar *)ID,
Packit 423ecb
					 (const xmlChar *)URL);
Packit 423ecb
	}
Packit 423ecb
	if ((resource == NULL) && (URL != NULL))
Packit 423ecb
	    resource = xmlStrdup((const xmlChar *) URL);
Packit 423ecb
Packit 423ecb
	/*
Packit 423ecb
	 * TODO: do an URI lookup on the reference
Packit 423ecb
	 */
Packit 423ecb
	if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
Packit 423ecb
	    xmlChar *tmp = NULL;
Packit 423ecb
Packit 423ecb
	    if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
Packit 423ecb
		((pref == XML_CATA_ALLOW_ALL) ||
Packit 423ecb
		 (pref == XML_CATA_ALLOW_DOCUMENT))) {
Packit 423ecb
		tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
Packit 423ecb
	    }
Packit 423ecb
	    if ((tmp == NULL) &&
Packit 423ecb
		((pref == XML_CATA_ALLOW_ALL) ||
Packit 423ecb
	         (pref == XML_CATA_ALLOW_GLOBAL))) {
Packit 423ecb
		tmp = xmlCatalogResolveURI(resource);
Packit 423ecb
	    }
Packit 423ecb
Packit 423ecb
	    if (tmp != NULL) {
Packit 423ecb
		xmlFree(resource);
Packit 423ecb
		resource = tmp;
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return resource;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlDefaultExternalEntityLoader:
Packit 423ecb
 * @URL:  the URL for the entity to load
Packit 423ecb
 * @ID:  the System ID for the entity to load
Packit 423ecb
 * @ctxt:  the context in which the entity is called or NULL
Packit 423ecb
 *
Packit 423ecb
 * By default we don't load external entitites, yet.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new allocated xmlParserInputPtr, or NULL.
Packit 423ecb
 */
Packit 423ecb
static xmlParserInputPtr
Packit 423ecb
xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
Packit 423ecb
                               xmlParserCtxtPtr ctxt)
Packit 423ecb
{
Packit 423ecb
    xmlParserInputPtr ret = NULL;
Packit 423ecb
    xmlChar *resource = NULL;
Packit 423ecb
Packit 423ecb
#ifdef DEBUG_EXTERNAL_ENTITIES
Packit 423ecb
    xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
                    "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
Packit 423ecb
#endif
Packit 423ecb
    if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
Packit 423ecb
        int options = ctxt->options;
Packit 423ecb
Packit 423ecb
	ctxt->options -= XML_PARSE_NONET;
Packit 423ecb
        ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
Packit 423ecb
	ctxt->options = options;
Packit 423ecb
	return(ret);
Packit 423ecb
    }
Packit 423ecb
#ifdef LIBXML_CATALOG_ENABLED
Packit 423ecb
    resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if (resource == NULL)
Packit 423ecb
        resource = (xmlChar *) URL;
Packit 423ecb
Packit 423ecb
    if (resource == NULL) {
Packit 423ecb
        if (ID == NULL)
Packit 423ecb
            ID = "NULL";
Packit 423ecb
        __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
Packit 423ecb
        return (NULL);
Packit 423ecb
    }
Packit 423ecb
    ret = xmlNewInputFromFile(ctxt, (const char *) resource);
Packit 423ecb
    if ((resource != NULL) && (resource != (xmlChar *) URL))
Packit 423ecb
        xmlFree(resource);
Packit 423ecb
    return (ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
Packit 423ecb
       xmlDefaultExternalEntityLoader;
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlSetExternalEntityLoader:
Packit 423ecb
 * @f:  the new entity resolver function
Packit 423ecb
 *
Packit 423ecb
 * Changes the defaultexternal entity resolver function for the application
Packit 423ecb
 */
Packit 423ecb
void
Packit 423ecb
xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
Packit 423ecb
    xmlCurrentExternalEntityLoader = f;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlGetExternalEntityLoader:
Packit 423ecb
 *
Packit 423ecb
 * Get the default external entity resolver function for the application
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlExternalEntityLoader function pointer
Packit 423ecb
 */
Packit 423ecb
xmlExternalEntityLoader
Packit 423ecb
xmlGetExternalEntityLoader(void) {
Packit 423ecb
    return(xmlCurrentExternalEntityLoader);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlLoadExternalEntity:
Packit 423ecb
 * @URL:  the URL for the entity to load
Packit 423ecb
 * @ID:  the Public ID for the entity to load
Packit 423ecb
 * @ctxt:  the context in which the entity is called or NULL
Packit 423ecb
 *
Packit 423ecb
 * Load an external entity, note that the use of this function for
Packit 423ecb
 * unparsed entities may generate problems
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlParserInputPtr or NULL
Packit 423ecb
 */
Packit 423ecb
xmlParserInputPtr
Packit 423ecb
xmlLoadExternalEntity(const char *URL, const char *ID,
Packit 423ecb
                      xmlParserCtxtPtr ctxt) {
Packit 423ecb
    if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
Packit 423ecb
	char *canonicFilename;
Packit 423ecb
	xmlParserInputPtr ret;
Packit 423ecb
Packit 423ecb
	canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
Packit 423ecb
	if (canonicFilename == NULL) {
Packit 423ecb
            xmlIOErrMemory("building canonical path\n");
Packit 423ecb
	    return(NULL);
Packit 423ecb
	}
Packit 423ecb
Packit 423ecb
	ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
Packit 423ecb
	xmlFree(canonicFilename);
Packit 423ecb
	return(ret);
Packit 423ecb
    }
Packit 423ecb
    return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Disabling Network access				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlNoNetExternalEntityLoader:
Packit 423ecb
 * @URL:  the URL for the entity to load
Packit 423ecb
 * @ID:  the System ID for the entity to load
Packit 423ecb
 * @ctxt:  the context in which the entity is called or NULL
Packit 423ecb
 *
Packit 423ecb
 * A specific entity loader disabling network accesses, though still
Packit 423ecb
 * allowing local catalog accesses for resolution.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new allocated xmlParserInputPtr, or NULL.
Packit 423ecb
 */
Packit 423ecb
xmlParserInputPtr
Packit 423ecb
xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
Packit 423ecb
                             xmlParserCtxtPtr ctxt) {
Packit 423ecb
    xmlParserInputPtr input = NULL;
Packit 423ecb
    xmlChar *resource = NULL;
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_CATALOG_ENABLED
Packit 423ecb
    resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if (resource == NULL)
Packit 423ecb
	resource = (xmlChar *) URL;
Packit 423ecb
Packit 423ecb
    if (resource != NULL) {
Packit 423ecb
        if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
Packit 423ecb
            (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
Packit 423ecb
            xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
Packit 423ecb
	    if (resource != (xmlChar *) URL)
Packit 423ecb
		xmlFree(resource);
Packit 423ecb
	    return(NULL);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
Packit 423ecb
    if (resource != (xmlChar *) URL)
Packit 423ecb
	xmlFree(resource);
Packit 423ecb
    return(input);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#define bottom_xmlIO
Packit 423ecb
#include "elfgcchack.h"