Annotation of embedaddon/libxml2/xmlIO.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * xmlIO.c : implementation of the I/O interfaces used by the parser
        !             3:  *
        !             4:  * See Copyright for the status of this software.
        !             5:  *
        !             6:  * daniel@veillard.com
        !             7:  *
        !             8:  * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
        !             9:  */
        !            10: 
        !            11: #define IN_LIBXML
        !            12: #include "libxml.h"
        !            13: 
        !            14: #include <string.h>
        !            15: #ifdef HAVE_ERRNO_H
        !            16: #include <errno.h>
        !            17: #endif
        !            18: 
        !            19: 
        !            20: #ifdef HAVE_SYS_TYPES_H
        !            21: #include <sys/types.h>
        !            22: #endif
        !            23: #ifdef HAVE_SYS_STAT_H
        !            24: #include <sys/stat.h>
        !            25: #endif
        !            26: #ifdef HAVE_FCNTL_H
        !            27: #include <fcntl.h>
        !            28: #endif
        !            29: #ifdef HAVE_UNISTD_H
        !            30: #include <unistd.h>
        !            31: #endif
        !            32: #ifdef HAVE_STDLIB_H
        !            33: #include <stdlib.h>
        !            34: #endif
        !            35: #ifdef HAVE_ZLIB_H
        !            36: #include <zlib.h>
        !            37: #endif
        !            38: 
        !            39: #if defined(WIN32) || defined(_WIN32)
        !            40: #include <windows.h>
        !            41: #endif
        !            42: 
        !            43: #if defined(_WIN32_WCE)
        !            44: #include <winnls.h> /* for CP_UTF8 */
        !            45: #endif
        !            46: 
        !            47: /* Figure a portable way to know if a file is a directory. */
        !            48: #ifndef HAVE_STAT
        !            49: #  ifdef HAVE__STAT
        !            50:      /* MS C library seems to define stat and _stat. The definition
        !            51:         is identical. Still, mapping them to each other causes a warning. */
        !            52: #    ifndef _MSC_VER
        !            53: #      define stat(x,y) _stat(x,y)
        !            54: #    endif
        !            55: #    define HAVE_STAT
        !            56: #  endif
        !            57: #else
        !            58: #  ifdef HAVE__STAT
        !            59: #    if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !            60: #      define stat _stat
        !            61: #    endif
        !            62: #  endif
        !            63: #endif
        !            64: #ifdef HAVE_STAT
        !            65: #  ifndef S_ISDIR
        !            66: #    ifdef _S_ISDIR
        !            67: #      define S_ISDIR(x) _S_ISDIR(x)
        !            68: #    else
        !            69: #      ifdef S_IFDIR
        !            70: #        ifndef S_IFMT
        !            71: #          ifdef _S_IFMT
        !            72: #            define S_IFMT _S_IFMT
        !            73: #          endif
        !            74: #        endif
        !            75: #        ifdef S_IFMT
        !            76: #          define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
        !            77: #        endif
        !            78: #      endif
        !            79: #    endif
        !            80: #  endif
        !            81: #endif
        !            82: 
        !            83: #include <libxml/xmlmemory.h>
        !            84: #include <libxml/parser.h>
        !            85: #include <libxml/parserInternals.h>
        !            86: #include <libxml/xmlIO.h>
        !            87: #include <libxml/uri.h>
        !            88: #include <libxml/nanohttp.h>
        !            89: #include <libxml/nanoftp.h>
        !            90: #include <libxml/xmlerror.h>
        !            91: #ifdef LIBXML_CATALOG_ENABLED
        !            92: #include <libxml/catalog.h>
        !            93: #endif
        !            94: #include <libxml/globals.h>
        !            95: 
        !            96: /* #define VERBOSE_FAILURE */
        !            97: /* #define DEBUG_EXTERNAL_ENTITIES */
        !            98: /* #define DEBUG_INPUT */
        !            99: 
        !           100: #ifdef DEBUG_INPUT
        !           101: #define MINLEN 40
        !           102: #else
        !           103: #define MINLEN 4000
        !           104: #endif
        !           105: 
        !           106: /*
        !           107:  * Input I/O callback sets
        !           108:  */
        !           109: typedef struct _xmlInputCallback {
        !           110:     xmlInputMatchCallback matchcallback;
        !           111:     xmlInputOpenCallback opencallback;
        !           112:     xmlInputReadCallback readcallback;
        !           113:     xmlInputCloseCallback closecallback;
        !           114: } xmlInputCallback;
        !           115: 
        !           116: #define MAX_INPUT_CALLBACK 15
        !           117: 
        !           118: static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
        !           119: static int xmlInputCallbackNr = 0;
        !           120: static int xmlInputCallbackInitialized = 0;
        !           121: 
        !           122: #ifdef LIBXML_OUTPUT_ENABLED
        !           123: /*
        !           124:  * Output I/O callback sets
        !           125:  */
        !           126: typedef struct _xmlOutputCallback {
        !           127:     xmlOutputMatchCallback matchcallback;
        !           128:     xmlOutputOpenCallback opencallback;
        !           129:     xmlOutputWriteCallback writecallback;
        !           130:     xmlOutputCloseCallback closecallback;
        !           131: } xmlOutputCallback;
        !           132: 
        !           133: #define MAX_OUTPUT_CALLBACK 15
        !           134: 
        !           135: static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
        !           136: static int xmlOutputCallbackNr = 0;
        !           137: static int xmlOutputCallbackInitialized = 0;
        !           138: 
        !           139: xmlOutputBufferPtr
        !           140: xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
        !           141: #endif /* LIBXML_OUTPUT_ENABLED */
        !           142: 
        !           143: /************************************************************************
        !           144:  *                                                                     *
        !           145:  *             Tree memory error handler                               *
        !           146:  *                                                                     *
        !           147:  ************************************************************************/
        !           148: 
        !           149: static const char *IOerr[] = {
        !           150:     "Unknown IO error",         /* UNKNOWN */
        !           151:     "Permission denied",       /* EACCES */
        !           152:     "Resource temporarily unavailable",/* EAGAIN */
        !           153:     "Bad file descriptor",     /* EBADF */
        !           154:     "Bad message",             /* EBADMSG */
        !           155:     "Resource busy",           /* EBUSY */
        !           156:     "Operation canceled",      /* ECANCELED */
        !           157:     "No child processes",      /* ECHILD */
        !           158:     "Resource deadlock avoided",/* EDEADLK */
        !           159:     "Domain error",            /* EDOM */
        !           160:     "File exists",             /* EEXIST */
        !           161:     "Bad address",             /* EFAULT */
        !           162:     "File too large",          /* EFBIG */
        !           163:     "Operation in progress",   /* EINPROGRESS */
        !           164:     "Interrupted function call",/* EINTR */
        !           165:     "Invalid argument",                /* EINVAL */
        !           166:     "Input/output error",      /* EIO */
        !           167:     "Is a directory",          /* EISDIR */
        !           168:     "Too many open files",     /* EMFILE */
        !           169:     "Too many links",          /* EMLINK */
        !           170:     "Inappropriate message buffer length",/* EMSGSIZE */
        !           171:     "Filename too long",       /* ENAMETOOLONG */
        !           172:     "Too many open files in system",/* ENFILE */
        !           173:     "No such device",          /* ENODEV */
        !           174:     "No such file or directory",/* ENOENT */
        !           175:     "Exec format error",       /* ENOEXEC */
        !           176:     "No locks available",      /* ENOLCK */
        !           177:     "Not enough space",                /* ENOMEM */
        !           178:     "No space left on device", /* ENOSPC */
        !           179:     "Function not implemented",        /* ENOSYS */
        !           180:     "Not a directory",         /* ENOTDIR */
        !           181:     "Directory not empty",     /* ENOTEMPTY */
        !           182:     "Not supported",           /* ENOTSUP */
        !           183:     "Inappropriate I/O control operation",/* ENOTTY */
        !           184:     "No such device or address",/* ENXIO */
        !           185:     "Operation not permitted", /* EPERM */
        !           186:     "Broken pipe",             /* EPIPE */
        !           187:     "Result too large",                /* ERANGE */
        !           188:     "Read-only file system",   /* EROFS */
        !           189:     "Invalid seek",            /* ESPIPE */
        !           190:     "No such process",         /* ESRCH */
        !           191:     "Operation timed out",     /* ETIMEDOUT */
        !           192:     "Improper link",           /* EXDEV */
        !           193:     "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
        !           194:     "encoder error",           /* XML_IO_ENCODER */
        !           195:     "flush error",
        !           196:     "write error",
        !           197:     "no input",
        !           198:     "buffer full",
        !           199:     "loading error",
        !           200:     "not a socket",            /* ENOTSOCK */
        !           201:     "already connected",       /* EISCONN */
        !           202:     "connection refused",      /* ECONNREFUSED */
        !           203:     "unreachable network",     /* ENETUNREACH */
        !           204:     "adddress in use",         /* EADDRINUSE */
        !           205:     "already in use",          /* EALREADY */
        !           206:     "unknown address familly", /* EAFNOSUPPORT */
        !           207: };
        !           208: 
        !           209: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !           210: /**
        !           211:  * __xmlIOWin32UTF8ToWChar:
        !           212:  * @u8String:  uft-8 string
        !           213:  *
        !           214:  * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
        !           215:  */
        !           216: static wchar_t *
        !           217: __xmlIOWin32UTF8ToWChar(const char *u8String)
        !           218: {
        !           219:     wchar_t *wString = NULL;
        !           220: 
        !           221:     if (u8String) {
        !           222:         int wLen =
        !           223:             MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
        !           224:                                 -1, NULL, 0);
        !           225:         if (wLen) {
        !           226:             wString = xmlMalloc(wLen * sizeof(wchar_t));
        !           227:             if (wString) {
        !           228:                 if (MultiByteToWideChar
        !           229:                     (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
        !           230:                     xmlFree(wString);
        !           231:                     wString = NULL;
        !           232:                 }
        !           233:             }
        !           234:         }
        !           235:     }
        !           236: 
        !           237:     return wString;
        !           238: }
        !           239: #endif
        !           240: 
        !           241: /**
        !           242:  * xmlIOErrMemory:
        !           243:  * @extra:  extra informations
        !           244:  *
        !           245:  * Handle an out of memory condition
        !           246:  */
        !           247: static void
        !           248: xmlIOErrMemory(const char *extra)
        !           249: {
        !           250:     __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
        !           251: }
        !           252: 
        !           253: /**
        !           254:  * __xmlIOErr:
        !           255:  * @code:  the error number
        !           256:  * @
        !           257:  * @extra:  extra informations
        !           258:  *
        !           259:  * Handle an I/O error
        !           260:  */
        !           261: void
        !           262: __xmlIOErr(int domain, int code, const char *extra)
        !           263: {
        !           264:     unsigned int idx;
        !           265: 
        !           266:     if (code == 0) {
        !           267: #ifdef HAVE_ERRNO_H
        !           268:        if (errno == 0) code = 0;
        !           269: #ifdef EACCES
        !           270:         else if (errno == EACCES) code = XML_IO_EACCES;
        !           271: #endif
        !           272: #ifdef EAGAIN
        !           273:         else if (errno == EAGAIN) code = XML_IO_EAGAIN;
        !           274: #endif
        !           275: #ifdef EBADF
        !           276:         else if (errno == EBADF) code = XML_IO_EBADF;
        !           277: #endif
        !           278: #ifdef EBADMSG
        !           279:         else if (errno == EBADMSG) code = XML_IO_EBADMSG;
        !           280: #endif
        !           281: #ifdef EBUSY
        !           282:         else if (errno == EBUSY) code = XML_IO_EBUSY;
        !           283: #endif
        !           284: #ifdef ECANCELED
        !           285:         else if (errno == ECANCELED) code = XML_IO_ECANCELED;
        !           286: #endif
        !           287: #ifdef ECHILD
        !           288:         else if (errno == ECHILD) code = XML_IO_ECHILD;
        !           289: #endif
        !           290: #ifdef EDEADLK
        !           291:         else if (errno == EDEADLK) code = XML_IO_EDEADLK;
        !           292: #endif
        !           293: #ifdef EDOM
        !           294:         else if (errno == EDOM) code = XML_IO_EDOM;
        !           295: #endif
        !           296: #ifdef EEXIST
        !           297:         else if (errno == EEXIST) code = XML_IO_EEXIST;
        !           298: #endif
        !           299: #ifdef EFAULT
        !           300:         else if (errno == EFAULT) code = XML_IO_EFAULT;
        !           301: #endif
        !           302: #ifdef EFBIG
        !           303:         else if (errno == EFBIG) code = XML_IO_EFBIG;
        !           304: #endif
        !           305: #ifdef EINPROGRESS
        !           306:         else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
        !           307: #endif
        !           308: #ifdef EINTR
        !           309:         else if (errno == EINTR) code = XML_IO_EINTR;
        !           310: #endif
        !           311: #ifdef EINVAL
        !           312:         else if (errno == EINVAL) code = XML_IO_EINVAL;
        !           313: #endif
        !           314: #ifdef EIO
        !           315:         else if (errno == EIO) code = XML_IO_EIO;
        !           316: #endif
        !           317: #ifdef EISDIR
        !           318:         else if (errno == EISDIR) code = XML_IO_EISDIR;
        !           319: #endif
        !           320: #ifdef EMFILE
        !           321:         else if (errno == EMFILE) code = XML_IO_EMFILE;
        !           322: #endif
        !           323: #ifdef EMLINK
        !           324:         else if (errno == EMLINK) code = XML_IO_EMLINK;
        !           325: #endif
        !           326: #ifdef EMSGSIZE
        !           327:         else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
        !           328: #endif
        !           329: #ifdef ENAMETOOLONG
        !           330:         else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
        !           331: #endif
        !           332: #ifdef ENFILE
        !           333:         else if (errno == ENFILE) code = XML_IO_ENFILE;
        !           334: #endif
        !           335: #ifdef ENODEV
        !           336:         else if (errno == ENODEV) code = XML_IO_ENODEV;
        !           337: #endif
        !           338: #ifdef ENOENT
        !           339:         else if (errno == ENOENT) code = XML_IO_ENOENT;
        !           340: #endif
        !           341: #ifdef ENOEXEC
        !           342:         else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
        !           343: #endif
        !           344: #ifdef ENOLCK
        !           345:         else if (errno == ENOLCK) code = XML_IO_ENOLCK;
        !           346: #endif
        !           347: #ifdef ENOMEM
        !           348:         else if (errno == ENOMEM) code = XML_IO_ENOMEM;
        !           349: #endif
        !           350: #ifdef ENOSPC
        !           351:         else if (errno == ENOSPC) code = XML_IO_ENOSPC;
        !           352: #endif
        !           353: #ifdef ENOSYS
        !           354:         else if (errno == ENOSYS) code = XML_IO_ENOSYS;
        !           355: #endif
        !           356: #ifdef ENOTDIR
        !           357:         else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
        !           358: #endif
        !           359: #ifdef ENOTEMPTY
        !           360:         else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
        !           361: #endif
        !           362: #ifdef ENOTSUP
        !           363:         else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
        !           364: #endif
        !           365: #ifdef ENOTTY
        !           366:         else if (errno == ENOTTY) code = XML_IO_ENOTTY;
        !           367: #endif
        !           368: #ifdef ENXIO
        !           369:         else if (errno == ENXIO) code = XML_IO_ENXIO;
        !           370: #endif
        !           371: #ifdef EPERM
        !           372:         else if (errno == EPERM) code = XML_IO_EPERM;
        !           373: #endif
        !           374: #ifdef EPIPE
        !           375:         else if (errno == EPIPE) code = XML_IO_EPIPE;
        !           376: #endif
        !           377: #ifdef ERANGE
        !           378:         else if (errno == ERANGE) code = XML_IO_ERANGE;
        !           379: #endif
        !           380: #ifdef EROFS
        !           381:         else if (errno == EROFS) code = XML_IO_EROFS;
        !           382: #endif
        !           383: #ifdef ESPIPE
        !           384:         else if (errno == ESPIPE) code = XML_IO_ESPIPE;
        !           385: #endif
        !           386: #ifdef ESRCH
        !           387:         else if (errno == ESRCH) code = XML_IO_ESRCH;
        !           388: #endif
        !           389: #ifdef ETIMEDOUT
        !           390:         else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
        !           391: #endif
        !           392: #ifdef EXDEV
        !           393:         else if (errno == EXDEV) code = XML_IO_EXDEV;
        !           394: #endif
        !           395: #ifdef ENOTSOCK
        !           396:         else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
        !           397: #endif
        !           398: #ifdef EISCONN
        !           399:         else if (errno == EISCONN) code = XML_IO_EISCONN;
        !           400: #endif
        !           401: #ifdef ECONNREFUSED
        !           402:         else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
        !           403: #endif
        !           404: #ifdef ETIMEDOUT
        !           405:         else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
        !           406: #endif
        !           407: #ifdef ENETUNREACH
        !           408:         else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
        !           409: #endif
        !           410: #ifdef EADDRINUSE
        !           411:         else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
        !           412: #endif
        !           413: #ifdef EINPROGRESS
        !           414:         else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
        !           415: #endif
        !           416: #ifdef EALREADY
        !           417:         else if (errno == EALREADY) code = XML_IO_EALREADY;
        !           418: #endif
        !           419: #ifdef EAFNOSUPPORT
        !           420:         else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
        !           421: #endif
        !           422:         else code = XML_IO_UNKNOWN;
        !           423: #endif /* HAVE_ERRNO_H */
        !           424:     }
        !           425:     idx = 0;
        !           426:     if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
        !           427:     if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
        !           428: 
        !           429:     __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
        !           430: }
        !           431: 
        !           432: /**
        !           433:  * xmlIOErr:
        !           434:  * @code:  the error number
        !           435:  * @extra:  extra informations
        !           436:  *
        !           437:  * Handle an I/O error
        !           438:  */
        !           439: static void
        !           440: xmlIOErr(int code, const char *extra)
        !           441: {
        !           442:     __xmlIOErr(XML_FROM_IO, code, extra);
        !           443: }
        !           444: 
        !           445: /**
        !           446:  * __xmlLoaderErr:
        !           447:  * @ctx: the parser context
        !           448:  * @extra:  extra informations
        !           449:  *
        !           450:  * Handle a resource access error
        !           451:  */
        !           452: void
        !           453: __xmlLoaderErr(void *ctx, const char *msg, const char *filename)
        !           454: {
        !           455:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        !           456:     xmlStructuredErrorFunc schannel = NULL;
        !           457:     xmlGenericErrorFunc channel = NULL;
        !           458:     void *data = NULL;
        !           459:     xmlErrorLevel level = XML_ERR_ERROR;
        !           460: 
        !           461:     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        !           462:         (ctxt->instate == XML_PARSER_EOF))
        !           463:        return;
        !           464:     if ((ctxt != NULL) && (ctxt->sax != NULL)) {
        !           465:         if (ctxt->validate) {
        !           466:            channel = ctxt->sax->error;
        !           467:            level = XML_ERR_ERROR;
        !           468:        } else {
        !           469:            channel = ctxt->sax->warning;
        !           470:            level = XML_ERR_WARNING;
        !           471:        }
        !           472:        if (ctxt->sax->initialized == XML_SAX2_MAGIC)
        !           473:            schannel = ctxt->sax->serror;
        !           474:        data = ctxt->userData;
        !           475:     }
        !           476:     __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
        !           477:                     XML_IO_LOAD_ERROR, level, NULL, 0,
        !           478:                    filename, NULL, NULL, 0, 0,
        !           479:                    msg, filename);
        !           480: 
        !           481: }
        !           482: 
        !           483: /************************************************************************
        !           484:  *                                                                     *
        !           485:  *             Tree memory error handler                               *
        !           486:  *                                                                     *
        !           487:  ************************************************************************/
        !           488: /**
        !           489:  * xmlNormalizeWindowsPath:
        !           490:  * @path: the input file path
        !           491:  *
        !           492:  * This function is obsolete. Please see xmlURIFromPath in uri.c for
        !           493:  * a better solution.
        !           494:  *
        !           495:  * Returns a canonicalized version of the path
        !           496:  */
        !           497: xmlChar *
        !           498: xmlNormalizeWindowsPath(const xmlChar *path)
        !           499: {
        !           500:     return xmlCanonicPath(path);
        !           501: }
        !           502: 
        !           503: /**
        !           504:  * xmlCleanupInputCallbacks:
        !           505:  *
        !           506:  * clears the entire input callback table. this includes the
        !           507:  * compiled-in I/O.
        !           508:  */
        !           509: void
        !           510: xmlCleanupInputCallbacks(void)
        !           511: {
        !           512:     int i;
        !           513: 
        !           514:     if (!xmlInputCallbackInitialized)
        !           515:         return;
        !           516: 
        !           517:     for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
        !           518:         xmlInputCallbackTable[i].matchcallback = NULL;
        !           519:         xmlInputCallbackTable[i].opencallback = NULL;
        !           520:         xmlInputCallbackTable[i].readcallback = NULL;
        !           521:         xmlInputCallbackTable[i].closecallback = NULL;
        !           522:     }
        !           523: 
        !           524:     xmlInputCallbackNr = 0;
        !           525:     xmlInputCallbackInitialized = 0;
        !           526: }
        !           527: 
        !           528: /**
        !           529:  * xmlPopInputCallbacks:
        !           530:  *
        !           531:  * Clear the top input callback from the input stack. this includes the
        !           532:  * compiled-in I/O.
        !           533:  *
        !           534:  * Returns the number of input callback registered or -1 in case of error.
        !           535:  */
        !           536: int
        !           537: xmlPopInputCallbacks(void)
        !           538: {
        !           539:     if (!xmlInputCallbackInitialized)
        !           540:         return(-1);
        !           541: 
        !           542:     if (xmlInputCallbackNr <= 0)
        !           543:         return(-1);
        !           544: 
        !           545:     xmlInputCallbackNr--;
        !           546:     xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
        !           547:     xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
        !           548:     xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
        !           549:     xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
        !           550: 
        !           551:     return(xmlInputCallbackNr);
        !           552: }
        !           553: 
        !           554: #ifdef LIBXML_OUTPUT_ENABLED
        !           555: /**
        !           556:  * xmlCleanupOutputCallbacks:
        !           557:  *
        !           558:  * clears the entire output callback table. this includes the
        !           559:  * compiled-in I/O callbacks.
        !           560:  */
        !           561: void
        !           562: xmlCleanupOutputCallbacks(void)
        !           563: {
        !           564:     int i;
        !           565: 
        !           566:     if (!xmlOutputCallbackInitialized)
        !           567:         return;
        !           568: 
        !           569:     for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
        !           570:         xmlOutputCallbackTable[i].matchcallback = NULL;
        !           571:         xmlOutputCallbackTable[i].opencallback = NULL;
        !           572:         xmlOutputCallbackTable[i].writecallback = NULL;
        !           573:         xmlOutputCallbackTable[i].closecallback = NULL;
        !           574:     }
        !           575: 
        !           576:     xmlOutputCallbackNr = 0;
        !           577:     xmlOutputCallbackInitialized = 0;
        !           578: }
        !           579: #endif /* LIBXML_OUTPUT_ENABLED */
        !           580: 
        !           581: /************************************************************************
        !           582:  *                                                                     *
        !           583:  *             Standard I/O for file accesses                          *
        !           584:  *                                                                     *
        !           585:  ************************************************************************/
        !           586: 
        !           587: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !           588: 
        !           589: /**
        !           590:  *  xmlWrapOpenUtf8:
        !           591:  * @path:  the path in utf-8 encoding
        !           592:  * @mode:  type of access (0 - read, 1 - write)
        !           593:  *
        !           594:  * function opens the file specified by @path
        !           595:  *
        !           596:  */
        !           597: static FILE*
        !           598: xmlWrapOpenUtf8(const char *path,int mode)
        !           599: {
        !           600:     FILE *fd = NULL;
        !           601:     wchar_t *wPath;
        !           602: 
        !           603:     wPath = __xmlIOWin32UTF8ToWChar(path);
        !           604:     if(wPath)
        !           605:     {
        !           606:        fd = _wfopen(wPath, mode ? L"wb" : L"rb");
        !           607:        xmlFree(wPath);
        !           608:     }
        !           609:     /* maybe path in native encoding */
        !           610:     if(fd == NULL)
        !           611:        fd = fopen(path, mode ? "wb" : "rb");
        !           612: 
        !           613:     return fd;
        !           614: }
        !           615: 
        !           616: #ifdef HAVE_ZLIB_H
        !           617: static gzFile
        !           618: xmlWrapGzOpenUtf8(const char *path, const char *mode)
        !           619: {
        !           620:     gzFile fd;
        !           621:     wchar_t *wPath;
        !           622: 
        !           623:     fd = gzopen (path, mode);
        !           624:     if (fd)
        !           625:         return fd;
        !           626: 
        !           627:     wPath = __xmlIOWin32UTF8ToWChar(path);
        !           628:     if(wPath)
        !           629:     {
        !           630:        int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
        !           631: #ifdef _O_BINARY
        !           632:         m |= (strstr(mode, "b") ? _O_BINARY : 0);
        !           633: #endif
        !           634:        d = _wopen(wPath, m);
        !           635:        if (d >= 0)
        !           636:            fd = gzdopen(d, mode);
        !           637:         xmlFree(wPath);
        !           638:     }
        !           639: 
        !           640:     return fd;
        !           641: }
        !           642: #endif
        !           643: 
        !           644: /**
        !           645:  *  xmlWrapStatUtf8:
        !           646:  * @path:  the path in utf-8 encoding
        !           647:  * @info:  structure that stores results
        !           648:  *
        !           649:  * function obtains information about the file or directory
        !           650:  *
        !           651:  */
        !           652: static int
        !           653: xmlWrapStatUtf8(const char *path,struct stat *info)
        !           654: {
        !           655: #ifdef HAVE_STAT
        !           656:     int retval = -1;
        !           657:     wchar_t *wPath;
        !           658: 
        !           659:     wPath = __xmlIOWin32UTF8ToWChar(path);
        !           660:     if (wPath)
        !           661:     {
        !           662:        retval = _wstat(wPath,info);
        !           663:        xmlFree(wPath);
        !           664:     }
        !           665:     /* maybe path in native encoding */
        !           666:     if(retval < 0)
        !           667:        retval = stat(path,info);
        !           668:     return retval;
        !           669: #else
        !           670:     return -1;
        !           671: #endif
        !           672: }
        !           673: 
        !           674: /**
        !           675:  *  xmlWrapOpenNative:
        !           676:  * @path:  the path
        !           677:  * @mode:  type of access (0 - read, 1 - write)
        !           678:  *
        !           679:  * function opens the file specified by @path
        !           680:  *
        !           681:  */
        !           682: static FILE*
        !           683: xmlWrapOpenNative(const char *path,int mode)
        !           684: {
        !           685:     return fopen(path,mode ? "wb" : "rb");
        !           686: }
        !           687: 
        !           688: /**
        !           689:  *  xmlWrapStatNative:
        !           690:  * @path:  the path
        !           691:  * @info:  structure that stores results
        !           692:  *
        !           693:  * function obtains information about the file or directory
        !           694:  *
        !           695:  */
        !           696: static int
        !           697: xmlWrapStatNative(const char *path,struct stat *info)
        !           698: {
        !           699: #ifdef HAVE_STAT
        !           700:     return stat(path,info);
        !           701: #else
        !           702:     return -1;
        !           703: #endif
        !           704: }
        !           705: 
        !           706: typedef int (* xmlWrapStatFunc) (const char *f, struct stat *s);
        !           707: static xmlWrapStatFunc xmlWrapStat = xmlWrapStatNative;
        !           708: typedef FILE* (* xmlWrapOpenFunc)(const char *f,int mode);
        !           709: static xmlWrapOpenFunc xmlWrapOpen = xmlWrapOpenNative;
        !           710: #ifdef HAVE_ZLIB_H
        !           711: typedef gzFile (* xmlWrapGzOpenFunc) (const char *f, const char *mode);
        !           712: static xmlWrapGzOpenFunc xmlWrapGzOpen = gzopen;
        !           713: #endif
        !           714: /**
        !           715:  * xmlInitPlatformSpecificIo:
        !           716:  *
        !           717:  * Initialize platform specific features.
        !           718:  */
        !           719: static void
        !           720: xmlInitPlatformSpecificIo(void)
        !           721: {
        !           722:     static int xmlPlatformIoInitialized = 0;
        !           723:     OSVERSIONINFO osvi;
        !           724: 
        !           725:     if(xmlPlatformIoInitialized)
        !           726:       return;
        !           727: 
        !           728:     osvi.dwOSVersionInfoSize = sizeof(osvi);
        !           729: 
        !           730:     if(GetVersionEx(&osvi) && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
        !           731:       xmlWrapStat = xmlWrapStatUtf8;
        !           732:       xmlWrapOpen = xmlWrapOpenUtf8;
        !           733: #ifdef HAVE_ZLIB_H
        !           734:       xmlWrapGzOpen = xmlWrapGzOpenUtf8;
        !           735: #endif
        !           736:     } else {
        !           737:       xmlWrapStat = xmlWrapStatNative;
        !           738:       xmlWrapOpen = xmlWrapOpenNative;
        !           739: #ifdef HAVE_ZLIB_H
        !           740:       xmlWrapGzOpen = gzopen;
        !           741: #endif
        !           742:     }
        !           743: 
        !           744:     xmlPlatformIoInitialized = 1;
        !           745:     return;
        !           746: }
        !           747: 
        !           748: #endif
        !           749: 
        !           750: /**
        !           751:  * xmlCheckFilename:
        !           752:  * @path:  the path to check
        !           753:  *
        !           754:  * function checks to see if @path is a valid source
        !           755:  * (file, socket...) for XML.
        !           756:  *
        !           757:  * if stat is not available on the target machine,
        !           758:  * returns 1.  if stat fails, returns 0 (if calling
        !           759:  * stat on the filename fails, it can't be right).
        !           760:  * if stat succeeds and the file is a directory,
        !           761:  * returns 2.  otherwise returns 1.
        !           762:  */
        !           763: 
        !           764: int
        !           765: xmlCheckFilename (const char *path)
        !           766: {
        !           767: #ifdef HAVE_STAT
        !           768:        struct stat stat_buffer;
        !           769: #endif
        !           770:        if (path == NULL)
        !           771:                return(0);
        !           772: 
        !           773: #ifdef HAVE_STAT
        !           774: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !           775:     if (xmlWrapStat(path, &stat_buffer) == -1)
        !           776:         return 0;
        !           777: #else
        !           778:     if (stat(path, &stat_buffer) == -1)
        !           779:         return 0;
        !           780: #endif
        !           781: #ifdef S_ISDIR
        !           782:     if (S_ISDIR(stat_buffer.st_mode))
        !           783:         return 2;
        !           784: #endif
        !           785: #endif /* HAVE_STAT */
        !           786:     return 1;
        !           787: }
        !           788: 
        !           789: static int
        !           790: xmlNop(void) {
        !           791:     return(0);
        !           792: }
        !           793: 
        !           794: /**
        !           795:  * xmlFdRead:
        !           796:  * @context:  the I/O context
        !           797:  * @buffer:  where to drop data
        !           798:  * @len:  number of bytes to read
        !           799:  *
        !           800:  * Read @len bytes to @buffer from the I/O channel.
        !           801:  *
        !           802:  * Returns the number of bytes written
        !           803:  */
        !           804: static int
        !           805: xmlFdRead (void * context, char * buffer, int len) {
        !           806:     int ret;
        !           807: 
        !           808:     ret = read((int) (long) context, &buffer[0], len);
        !           809:     if (ret < 0) xmlIOErr(0, "read()");
        !           810:     return(ret);
        !           811: }
        !           812: 
        !           813: #ifdef LIBXML_OUTPUT_ENABLED
        !           814: /**
        !           815:  * xmlFdWrite:
        !           816:  * @context:  the I/O context
        !           817:  * @buffer:  where to get data
        !           818:  * @len:  number of bytes to write
        !           819:  *
        !           820:  * Write @len bytes from @buffer to the I/O channel.
        !           821:  *
        !           822:  * Returns the number of bytes written
        !           823:  */
        !           824: static int
        !           825: xmlFdWrite (void * context, const char * buffer, int len) {
        !           826:     int ret = 0;
        !           827: 
        !           828:     if (len > 0) {
        !           829:        ret = write((int) (long) context, &buffer[0], len);
        !           830:        if (ret < 0) xmlIOErr(0, "write()");
        !           831:     }
        !           832:     return(ret);
        !           833: }
        !           834: #endif /* LIBXML_OUTPUT_ENABLED */
        !           835: 
        !           836: /**
        !           837:  * xmlFdClose:
        !           838:  * @context:  the I/O context
        !           839:  *
        !           840:  * Close an I/O channel
        !           841:  *
        !           842:  * Returns 0 in case of success and error code otherwise
        !           843:  */
        !           844: static int
        !           845: xmlFdClose (void * context) {
        !           846:     int ret;
        !           847:     ret = close((int) (long) context);
        !           848:     if (ret < 0) xmlIOErr(0, "close()");
        !           849:     return(ret);
        !           850: }
        !           851: 
        !           852: /**
        !           853:  * xmlFileMatch:
        !           854:  * @filename:  the URI for matching
        !           855:  *
        !           856:  * input from FILE *
        !           857:  *
        !           858:  * Returns 1 if matches, 0 otherwise
        !           859:  */
        !           860: int
        !           861: xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
        !           862:     return(1);
        !           863: }
        !           864: 
        !           865: /**
        !           866:  * xmlFileOpen_real:
        !           867:  * @filename:  the URI for matching
        !           868:  *
        !           869:  * input from FILE *, supports compressed input
        !           870:  * if @filename is " " then the standard input is used
        !           871:  *
        !           872:  * Returns an I/O context or NULL in case of error
        !           873:  */
        !           874: static void *
        !           875: xmlFileOpen_real (const char *filename) {
        !           876:     const char *path = NULL;
        !           877:     FILE *fd;
        !           878: 
        !           879:     if (filename == NULL)
        !           880:         return(NULL);
        !           881: 
        !           882:     if (!strcmp(filename, "-")) {
        !           883:        fd = stdin;
        !           884:        return((void *) fd);
        !           885:     }
        !           886: 
        !           887:     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
        !           888: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !           889:        path = &filename[17];
        !           890: #else
        !           891:        path = &filename[16];
        !           892: #endif
        !           893:     } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
        !           894: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !           895:        path = &filename[8];
        !           896: #else
        !           897:        path = &filename[7];
        !           898: #endif
        !           899:     } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
        !           900:         /* lots of generators seems to lazy to read RFC 1738 */
        !           901: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !           902:        path = &filename[6];
        !           903: #else
        !           904:        path = &filename[5];
        !           905: #endif
        !           906:     } else
        !           907:        path = filename;
        !           908: 
        !           909:     if (path == NULL)
        !           910:        return(NULL);
        !           911:     if (!xmlCheckFilename(path))
        !           912:         return(NULL);
        !           913: 
        !           914: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !           915:     fd = xmlWrapOpen(path, 0);
        !           916: #else
        !           917:     fd = fopen(path, "r");
        !           918: #endif /* WIN32 */
        !           919:     if (fd == NULL) xmlIOErr(0, path);
        !           920:     return((void *) fd);
        !           921: }
        !           922: 
        !           923: /**
        !           924:  * xmlFileOpen:
        !           925:  * @filename:  the URI for matching
        !           926:  *
        !           927:  * Wrapper around xmlFileOpen_real that try it with an unescaped
        !           928:  * version of @filename, if this fails fallback to @filename
        !           929:  *
        !           930:  * Returns a handler or NULL in case or failure
        !           931:  */
        !           932: void *
        !           933: xmlFileOpen (const char *filename) {
        !           934:     char *unescaped;
        !           935:     void *retval;
        !           936: 
        !           937:     retval = xmlFileOpen_real(filename);
        !           938:     if (retval == NULL) {
        !           939:        unescaped = xmlURIUnescapeString(filename, 0, NULL);
        !           940:        if (unescaped != NULL) {
        !           941:            retval = xmlFileOpen_real(unescaped);
        !           942:            xmlFree(unescaped);
        !           943:        }
        !           944:     }
        !           945: 
        !           946:     return retval;
        !           947: }
        !           948: 
        !           949: #ifdef LIBXML_OUTPUT_ENABLED
        !           950: /**
        !           951:  * xmlFileOpenW:
        !           952:  * @filename:  the URI for matching
        !           953:  *
        !           954:  * output to from FILE *,
        !           955:  * if @filename is "-" then the standard output is used
        !           956:  *
        !           957:  * Returns an I/O context or NULL in case of error
        !           958:  */
        !           959: static void *
        !           960: xmlFileOpenW (const char *filename) {
        !           961:     const char *path = NULL;
        !           962:     FILE *fd;
        !           963: 
        !           964:     if (!strcmp(filename, "-")) {
        !           965:        fd = stdout;
        !           966:        return((void *) fd);
        !           967:     }
        !           968: 
        !           969:     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
        !           970: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !           971:        path = &filename[17];
        !           972: #else
        !           973:        path = &filename[16];
        !           974: #endif
        !           975:     else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
        !           976: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !           977:        path = &filename[8];
        !           978: #else
        !           979:        path = &filename[7];
        !           980: #endif
        !           981:     } else
        !           982:        path = filename;
        !           983: 
        !           984:     if (path == NULL)
        !           985:        return(NULL);
        !           986: 
        !           987: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !           988:     fd = xmlWrapOpen(path, 1);
        !           989: #else
        !           990:           fd = fopen(path, "wb");
        !           991: #endif /* WIN32 */
        !           992: 
        !           993:         if (fd == NULL) xmlIOErr(0, path);
        !           994:     return((void *) fd);
        !           995: }
        !           996: #endif /* LIBXML_OUTPUT_ENABLED */
        !           997: 
        !           998: /**
        !           999:  * xmlFileRead:
        !          1000:  * @context:  the I/O context
        !          1001:  * @buffer:  where to drop data
        !          1002:  * @len:  number of bytes to write
        !          1003:  *
        !          1004:  * Read @len bytes to @buffer from the I/O channel.
        !          1005:  *
        !          1006:  * Returns the number of bytes written or < 0 in case of failure
        !          1007:  */
        !          1008: int
        !          1009: xmlFileRead (void * context, char * buffer, int len) {
        !          1010:     int ret;
        !          1011:     if ((context == NULL) || (buffer == NULL))
        !          1012:         return(-1);
        !          1013:     ret = fread(&buffer[0], 1,  len, (FILE *) context);
        !          1014:     if (ret < 0) xmlIOErr(0, "fread()");
        !          1015:     return(ret);
        !          1016: }
        !          1017: 
        !          1018: #ifdef LIBXML_OUTPUT_ENABLED
        !          1019: /**
        !          1020:  * xmlFileWrite:
        !          1021:  * @context:  the I/O context
        !          1022:  * @buffer:  where to drop data
        !          1023:  * @len:  number of bytes to write
        !          1024:  *
        !          1025:  * Write @len bytes from @buffer to the I/O channel.
        !          1026:  *
        !          1027:  * Returns the number of bytes written
        !          1028:  */
        !          1029: static int
        !          1030: xmlFileWrite (void * context, const char * buffer, int len) {
        !          1031:     int items;
        !          1032: 
        !          1033:     if ((context == NULL) || (buffer == NULL))
        !          1034:         return(-1);
        !          1035:     items = fwrite(&buffer[0], len, 1, (FILE *) context);
        !          1036:     if ((items == 0) && (ferror((FILE *) context))) {
        !          1037:         xmlIOErr(0, "fwrite()");
        !          1038:        return(-1);
        !          1039:     }
        !          1040:     return(items * len);
        !          1041: }
        !          1042: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1043: 
        !          1044: /**
        !          1045:  * xmlFileClose:
        !          1046:  * @context:  the I/O context
        !          1047:  *
        !          1048:  * Close an I/O channel
        !          1049:  *
        !          1050:  * Returns 0 or -1 in case of error
        !          1051:  */
        !          1052: int
        !          1053: xmlFileClose (void * context) {
        !          1054:     FILE *fil;
        !          1055:     int ret;
        !          1056: 
        !          1057:     if (context == NULL)
        !          1058:         return(-1);
        !          1059:     fil = (FILE *) context;
        !          1060:     if ((fil == stdout) || (fil == stderr)) {
        !          1061:         ret = fflush(fil);
        !          1062:        if (ret < 0)
        !          1063:            xmlIOErr(0, "fflush()");
        !          1064:        return(0);
        !          1065:     }
        !          1066:     if (fil == stdin)
        !          1067:        return(0);
        !          1068:     ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
        !          1069:     if (ret < 0)
        !          1070:         xmlIOErr(0, "fclose()");
        !          1071:     return(ret);
        !          1072: }
        !          1073: 
        !          1074: /**
        !          1075:  * xmlFileFlush:
        !          1076:  * @context:  the I/O context
        !          1077:  *
        !          1078:  * Flush an I/O channel
        !          1079:  */
        !          1080: static int
        !          1081: xmlFileFlush (void * context) {
        !          1082:     int ret;
        !          1083: 
        !          1084:     if (context == NULL)
        !          1085:         return(-1);
        !          1086:     ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
        !          1087:     if (ret < 0)
        !          1088:         xmlIOErr(0, "fflush()");
        !          1089:     return(ret);
        !          1090: }
        !          1091: 
        !          1092: #ifdef LIBXML_OUTPUT_ENABLED
        !          1093: /**
        !          1094:  * xmlBufferWrite:
        !          1095:  * @context:  the xmlBuffer
        !          1096:  * @buffer:  the data to write
        !          1097:  * @len:  number of bytes to write
        !          1098:  *
        !          1099:  * Write @len bytes from @buffer to the xml buffer
        !          1100:  *
        !          1101:  * Returns the number of bytes written
        !          1102:  */
        !          1103: static int
        !          1104: xmlBufferWrite (void * context, const char * buffer, int len) {
        !          1105:     int ret;
        !          1106: 
        !          1107:     ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
        !          1108:     if (ret != 0)
        !          1109:         return(-1);
        !          1110:     return(len);
        !          1111: }
        !          1112: #endif
        !          1113: 
        !          1114: #ifdef HAVE_ZLIB_H
        !          1115: /************************************************************************
        !          1116:  *                                                                     *
        !          1117:  *             I/O for compressed file accesses                        *
        !          1118:  *                                                                     *
        !          1119:  ************************************************************************/
        !          1120: /**
        !          1121:  * xmlGzfileMatch:
        !          1122:  * @filename:  the URI for matching
        !          1123:  *
        !          1124:  * input from compressed file test
        !          1125:  *
        !          1126:  * Returns 1 if matches, 0 otherwise
        !          1127:  */
        !          1128: static int
        !          1129: xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
        !          1130:     return(1);
        !          1131: }
        !          1132: 
        !          1133: /**
        !          1134:  * xmlGzfileOpen_real:
        !          1135:  * @filename:  the URI for matching
        !          1136:  *
        !          1137:  * input from compressed file open
        !          1138:  * if @filename is " " then the standard input is used
        !          1139:  *
        !          1140:  * Returns an I/O context or NULL in case of error
        !          1141:  */
        !          1142: static void *
        !          1143: xmlGzfileOpen_real (const char *filename) {
        !          1144:     const char *path = NULL;
        !          1145:     gzFile fd;
        !          1146: 
        !          1147:     if (!strcmp(filename, "-")) {
        !          1148:         fd = gzdopen(dup(0), "rb");
        !          1149:        return((void *) fd);
        !          1150:     }
        !          1151: 
        !          1152:     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
        !          1153: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !          1154:        path = &filename[17];
        !          1155: #else
        !          1156:        path = &filename[16];
        !          1157: #endif
        !          1158:     else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
        !          1159: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !          1160:        path = &filename[8];
        !          1161: #else
        !          1162:        path = &filename[7];
        !          1163: #endif
        !          1164:     } else
        !          1165:        path = filename;
        !          1166: 
        !          1167:     if (path == NULL)
        !          1168:        return(NULL);
        !          1169:     if (!xmlCheckFilename(path))
        !          1170:         return(NULL);
        !          1171: 
        !          1172: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !          1173:     fd = xmlWrapGzOpen(path, "rb");
        !          1174: #else
        !          1175:     fd = gzopen(path, "rb");
        !          1176: #endif
        !          1177:     return((void *) fd);
        !          1178: }
        !          1179: 
        !          1180: /**
        !          1181:  * xmlGzfileOpen:
        !          1182:  * @filename:  the URI for matching
        !          1183:  *
        !          1184:  * Wrapper around xmlGzfileOpen if the open fais, it will
        !          1185:  * try to unescape @filename
        !          1186:  */
        !          1187: static void *
        !          1188: xmlGzfileOpen (const char *filename) {
        !          1189:     char *unescaped;
        !          1190:     void *retval;
        !          1191: 
        !          1192:     retval = xmlGzfileOpen_real(filename);
        !          1193:     if (retval == NULL) {
        !          1194:        unescaped = xmlURIUnescapeString(filename, 0, NULL);
        !          1195:        if (unescaped != NULL) {
        !          1196:            retval = xmlGzfileOpen_real(unescaped);
        !          1197:        }
        !          1198:        xmlFree(unescaped);
        !          1199:     }
        !          1200:     return retval;
        !          1201: }
        !          1202: 
        !          1203: #ifdef LIBXML_OUTPUT_ENABLED
        !          1204: /**
        !          1205:  * xmlGzfileOpenW:
        !          1206:  * @filename:  the URI for matching
        !          1207:  * @compression:  the compression factor (0 - 9 included)
        !          1208:  *
        !          1209:  * input from compressed file open
        !          1210:  * if @filename is " " then the standard input is used
        !          1211:  *
        !          1212:  * Returns an I/O context or NULL in case of error
        !          1213:  */
        !          1214: static void *
        !          1215: xmlGzfileOpenW (const char *filename, int compression) {
        !          1216:     const char *path = NULL;
        !          1217:     char mode[15];
        !          1218:     gzFile fd;
        !          1219: 
        !          1220:     snprintf(mode, sizeof(mode), "wb%d", compression);
        !          1221:     if (!strcmp(filename, "-")) {
        !          1222:         fd = gzdopen(dup(1), mode);
        !          1223:        return((void *) fd);
        !          1224:     }
        !          1225: 
        !          1226:     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
        !          1227: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !          1228:        path = &filename[17];
        !          1229: #else
        !          1230:        path = &filename[16];
        !          1231: #endif
        !          1232:     else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
        !          1233: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !          1234:        path = &filename[8];
        !          1235: #else
        !          1236:        path = &filename[7];
        !          1237: #endif
        !          1238:     } else
        !          1239:        path = filename;
        !          1240: 
        !          1241:     if (path == NULL)
        !          1242:        return(NULL);
        !          1243: 
        !          1244: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !          1245:     fd = xmlWrapGzOpen(path, mode);
        !          1246: #else
        !          1247:     fd = gzopen(path, mode);
        !          1248: #endif
        !          1249:     return((void *) fd);
        !          1250: }
        !          1251: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1252: 
        !          1253: /**
        !          1254:  * xmlGzfileRead:
        !          1255:  * @context:  the I/O context
        !          1256:  * @buffer:  where to drop data
        !          1257:  * @len:  number of bytes to write
        !          1258:  *
        !          1259:  * Read @len bytes to @buffer from the compressed I/O channel.
        !          1260:  *
        !          1261:  * Returns the number of bytes written
        !          1262:  */
        !          1263: static int
        !          1264: xmlGzfileRead (void * context, char * buffer, int len) {
        !          1265:     int ret;
        !          1266: 
        !          1267:     ret = gzread((gzFile) context, &buffer[0], len);
        !          1268:     if (ret < 0) xmlIOErr(0, "gzread()");
        !          1269:     return(ret);
        !          1270: }
        !          1271: 
        !          1272: #ifdef LIBXML_OUTPUT_ENABLED
        !          1273: /**
        !          1274:  * xmlGzfileWrite:
        !          1275:  * @context:  the I/O context
        !          1276:  * @buffer:  where to drop data
        !          1277:  * @len:  number of bytes to write
        !          1278:  *
        !          1279:  * Write @len bytes from @buffer to the compressed I/O channel.
        !          1280:  *
        !          1281:  * Returns the number of bytes written
        !          1282:  */
        !          1283: static int
        !          1284: xmlGzfileWrite (void * context, const char * buffer, int len) {
        !          1285:     int ret;
        !          1286: 
        !          1287:     ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
        !          1288:     if (ret < 0) xmlIOErr(0, "gzwrite()");
        !          1289:     return(ret);
        !          1290: }
        !          1291: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1292: 
        !          1293: /**
        !          1294:  * xmlGzfileClose:
        !          1295:  * @context:  the I/O context
        !          1296:  *
        !          1297:  * Close a compressed I/O channel
        !          1298:  */
        !          1299: static int
        !          1300: xmlGzfileClose (void * context) {
        !          1301:     int ret;
        !          1302: 
        !          1303:     ret =  (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
        !          1304:     if (ret < 0) xmlIOErr(0, "gzclose()");
        !          1305:     return(ret);
        !          1306: }
        !          1307: #endif /* HAVE_ZLIB_H */
        !          1308: 
        !          1309: #ifdef LIBXML_HTTP_ENABLED
        !          1310: /************************************************************************
        !          1311:  *                                                                     *
        !          1312:  *                     I/O for HTTP file accesses                      *
        !          1313:  *                                                                     *
        !          1314:  ************************************************************************/
        !          1315: 
        !          1316: #ifdef LIBXML_OUTPUT_ENABLED
        !          1317: typedef struct xmlIOHTTPWriteCtxt_
        !          1318: {
        !          1319:     int                        compression;
        !          1320: 
        !          1321:     char *             uri;
        !          1322: 
        !          1323:     void *             doc_buff;
        !          1324: 
        !          1325: } xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
        !          1326: 
        !          1327: #ifdef HAVE_ZLIB_H
        !          1328: 
        !          1329: #define DFLT_WBITS             ( -15 )
        !          1330: #define DFLT_MEM_LVL           ( 8 )
        !          1331: #define GZ_MAGIC1              ( 0x1f )
        !          1332: #define GZ_MAGIC2              ( 0x8b )
        !          1333: #define LXML_ZLIB_OS_CODE      ( 0x03 )
        !          1334: #define INIT_HTTP_BUFF_SIZE    ( 32768 )
        !          1335: #define DFLT_ZLIB_RATIO                ( 5 )
        !          1336: 
        !          1337: /*
        !          1338: **  Data structure and functions to work with sending compressed data
        !          1339: **  via HTTP.
        !          1340: */
        !          1341: 
        !          1342: typedef struct xmlZMemBuff_
        !          1343: {
        !          1344:    unsigned long       size;
        !          1345:    unsigned long       crc;
        !          1346: 
        !          1347:    unsigned char *     zbuff;
        !          1348:    z_stream            zctrl;
        !          1349: 
        !          1350: } xmlZMemBuff, *xmlZMemBuffPtr;
        !          1351: 
        !          1352: /**
        !          1353:  * append_reverse_ulong
        !          1354:  * @buff:  Compressed memory buffer
        !          1355:  * @data:  Unsigned long to append
        !          1356:  *
        !          1357:  * Append a unsigned long in reverse byte order to the end of the
        !          1358:  * memory buffer.
        !          1359:  */
        !          1360: static void
        !          1361: append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
        !          1362: 
        !          1363:     int                idx;
        !          1364: 
        !          1365:     if ( buff == NULL )
        !          1366:        return;
        !          1367: 
        !          1368:     /*
        !          1369:     **  This is plagiarized from putLong in gzio.c (zlib source) where
        !          1370:     **  the number "4" is hardcoded.  If zlib is ever patched to
        !          1371:     **  support 64 bit file sizes, this code would need to be patched
        !          1372:     **  as well.
        !          1373:     */
        !          1374: 
        !          1375:     for ( idx = 0; idx < 4; idx++ ) {
        !          1376:        *buff->zctrl.next_out = ( data & 0xff );
        !          1377:        data >>= 8;
        !          1378:        buff->zctrl.next_out++;
        !          1379:     }
        !          1380: 
        !          1381:     return;
        !          1382: }
        !          1383: 
        !          1384: /**
        !          1385:  *
        !          1386:  * xmlFreeZMemBuff
        !          1387:  * @buff:  The memory buffer context to clear
        !          1388:  *
        !          1389:  * Release all the resources associated with the compressed memory buffer.
        !          1390:  */
        !          1391: static void
        !          1392: xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
        !          1393: 
        !          1394: #ifdef DEBUG_HTTP
        !          1395:     int z_err;
        !          1396: #endif
        !          1397: 
        !          1398:     if ( buff == NULL )
        !          1399:        return;
        !          1400: 
        !          1401:     xmlFree( buff->zbuff );
        !          1402: #ifdef DEBUG_HTTP
        !          1403:     z_err = deflateEnd( &buff->zctrl );
        !          1404:     if ( z_err != Z_OK )
        !          1405:        xmlGenericError( xmlGenericErrorContext,
        !          1406:                        "xmlFreeZMemBuff:  Error releasing zlib context:  %d\n",
        !          1407:                        z_err );
        !          1408: #else
        !          1409:     deflateEnd( &buff->zctrl );
        !          1410: #endif
        !          1411: 
        !          1412:     xmlFree( buff );
        !          1413:     return;
        !          1414: }
        !          1415: 
        !          1416: /**
        !          1417:  * xmlCreateZMemBuff
        !          1418:  *@compression:        Compression value to use
        !          1419:  *
        !          1420:  * Create a memory buffer to hold the compressed XML document.  The
        !          1421:  * compressed document in memory will end up being identical to what
        !          1422:  * would be created if gzopen/gzwrite/gzclose were being used to
        !          1423:  * write the document to disk.  The code for the header/trailer data to
        !          1424:  * the compression is plagiarized from the zlib source files.
        !          1425:  */
        !          1426: static void *
        !          1427: xmlCreateZMemBuff( int compression ) {
        !          1428: 
        !          1429:     int                        z_err;
        !          1430:     int                        hdr_lgth;
        !          1431:     xmlZMemBuffPtr     buff = NULL;
        !          1432: 
        !          1433:     if ( ( compression < 1 ) || ( compression > 9 ) )
        !          1434:        return ( NULL );
        !          1435: 
        !          1436:     /*  Create the control and data areas  */
        !          1437: 
        !          1438:     buff = xmlMalloc( sizeof( xmlZMemBuff ) );
        !          1439:     if ( buff == NULL ) {
        !          1440:        xmlIOErrMemory("creating buffer context");
        !          1441:        return ( NULL );
        !          1442:     }
        !          1443: 
        !          1444:     (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
        !          1445:     buff->size = INIT_HTTP_BUFF_SIZE;
        !          1446:     buff->zbuff = xmlMalloc( buff->size );
        !          1447:     if ( buff->zbuff == NULL ) {
        !          1448:        xmlFreeZMemBuff( buff );
        !          1449:        xmlIOErrMemory("creating buffer");
        !          1450:        return ( NULL );
        !          1451:     }
        !          1452: 
        !          1453:     z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
        !          1454:                            DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
        !          1455:     if ( z_err != Z_OK ) {
        !          1456:        xmlChar msg[500];
        !          1457:        xmlFreeZMemBuff( buff );
        !          1458:        buff = NULL;
        !          1459:        xmlStrPrintf(msg, 500,
        !          1460:                    (const xmlChar *) "xmlCreateZMemBuff:  %s %d\n",
        !          1461:                    "Error initializing compression context.  ZLIB error:",
        !          1462:                    z_err );
        !          1463:        xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          1464:        return ( NULL );
        !          1465:     }
        !          1466: 
        !          1467:     /*  Set the header data.  The CRC will be needed for the trailer  */
        !          1468:     buff->crc = crc32( 0L, NULL, 0 );
        !          1469:     hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
        !          1470:                        "%c%c%c%c%c%c%c%c%c%c",
        !          1471:                        GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
        !          1472:                        0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
        !          1473:     buff->zctrl.next_out  = buff->zbuff + hdr_lgth;
        !          1474:     buff->zctrl.avail_out = buff->size - hdr_lgth;
        !          1475: 
        !          1476:     return ( buff );
        !          1477: }
        !          1478: 
        !          1479: /**
        !          1480:  * xmlZMemBuffExtend
        !          1481:  * @buff:  Buffer used to compress and consolidate data.
        !          1482:  * @ext_amt:   Number of bytes to extend the buffer.
        !          1483:  *
        !          1484:  * Extend the internal buffer used to store the compressed data by the
        !          1485:  * specified amount.
        !          1486:  *
        !          1487:  * Returns 0 on success or -1 on failure to extend the buffer.  On failure
        !          1488:  * the original buffer still exists at the original size.
        !          1489:  */
        !          1490: static int
        !          1491: xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
        !          1492: 
        !          1493:     int                        rc = -1;
        !          1494:     size_t             new_size;
        !          1495:     size_t             cur_used;
        !          1496: 
        !          1497:     unsigned char *    tmp_ptr = NULL;
        !          1498: 
        !          1499:     if ( buff == NULL )
        !          1500:        return ( -1 );
        !          1501: 
        !          1502:     else if ( ext_amt == 0 )
        !          1503:        return ( 0 );
        !          1504: 
        !          1505:     cur_used = buff->zctrl.next_out - buff->zbuff;
        !          1506:     new_size = buff->size + ext_amt;
        !          1507: 
        !          1508: #ifdef DEBUG_HTTP
        !          1509:     if ( cur_used > new_size )
        !          1510:        xmlGenericError( xmlGenericErrorContext,
        !          1511:                        "xmlZMemBuffExtend:  %s\n%s %d bytes.\n",
        !          1512:                        "Buffer overwrite detected during compressed memory",
        !          1513:                        "buffer extension.  Overflowed by",
        !          1514:                        (cur_used - new_size ) );
        !          1515: #endif
        !          1516: 
        !          1517:     tmp_ptr = xmlRealloc( buff->zbuff, new_size );
        !          1518:     if ( tmp_ptr != NULL ) {
        !          1519:        rc = 0;
        !          1520:        buff->size  = new_size;
        !          1521:        buff->zbuff = tmp_ptr;
        !          1522:        buff->zctrl.next_out  = tmp_ptr + cur_used;
        !          1523:        buff->zctrl.avail_out = new_size - cur_used;
        !          1524:     }
        !          1525:     else {
        !          1526:        xmlChar msg[500];
        !          1527:        xmlStrPrintf(msg, 500,
        !          1528:                    (const xmlChar *) "xmlZMemBuffExtend:  %s %lu bytes.\n",
        !          1529:                    "Allocation failure extending output buffer to",
        !          1530:                    new_size );
        !          1531:        xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          1532:     }
        !          1533: 
        !          1534:     return ( rc );
        !          1535: }
        !          1536: 
        !          1537: /**
        !          1538:  * xmlZMemBuffAppend
        !          1539:  * @buff:  Buffer used to compress and consolidate data
        !          1540:  * @src:   Uncompressed source content to append to buffer
        !          1541:  * @len:   Length of source data to append to buffer
        !          1542:  *
        !          1543:  * Compress and append data to the internal buffer.  The data buffer
        !          1544:  * will be expanded if needed to store the additional data.
        !          1545:  *
        !          1546:  * Returns the number of bytes appended to the buffer or -1 on error.
        !          1547:  */
        !          1548: static int
        !          1549: xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
        !          1550: 
        !          1551:     int                z_err;
        !          1552:     size_t     min_accept;
        !          1553: 
        !          1554:     if ( ( buff == NULL ) || ( src == NULL ) )
        !          1555:        return ( -1 );
        !          1556: 
        !          1557:     buff->zctrl.avail_in = len;
        !          1558:     buff->zctrl.next_in  = (unsigned char *)src;
        !          1559:     while ( buff->zctrl.avail_in > 0 ) {
        !          1560:        /*
        !          1561:        **  Extend the buffer prior to deflate call if a reasonable amount
        !          1562:        **  of output buffer space is not available.
        !          1563:        */
        !          1564:        min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
        !          1565:        if ( buff->zctrl.avail_out <= min_accept ) {
        !          1566:            if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
        !          1567:                return ( -1 );
        !          1568:        }
        !          1569: 
        !          1570:        z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
        !          1571:        if ( z_err != Z_OK ) {
        !          1572:            xmlChar msg[500];
        !          1573:            xmlStrPrintf(msg, 500,
        !          1574:                        (const xmlChar *) "xmlZMemBuffAppend:  %s %d %s - %d",
        !          1575:                        "Compression error while appending",
        !          1576:                        len, "bytes to buffer.  ZLIB error", z_err );
        !          1577:            xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          1578:            return ( -1 );
        !          1579:        }
        !          1580:     }
        !          1581: 
        !          1582:     buff->crc = crc32( buff->crc, (unsigned char *)src, len );
        !          1583: 
        !          1584:     return ( len );
        !          1585: }
        !          1586: 
        !          1587: /**
        !          1588:  * xmlZMemBuffGetContent
        !          1589:  * @buff:  Compressed memory content buffer
        !          1590:  * @data_ref:  Pointer reference to point to compressed content
        !          1591:  *
        !          1592:  * Flushes the compression buffers, appends gzip file trailers and
        !          1593:  * returns the compressed content and length of the compressed data.
        !          1594:  * NOTE:  The gzip trailer code here is plagiarized from zlib source.
        !          1595:  *
        !          1596:  * Returns the length of the compressed data or -1 on error.
        !          1597:  */
        !          1598: static int
        !          1599: xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
        !          1600: 
        !          1601:     int                zlgth = -1;
        !          1602:     int                z_err;
        !          1603: 
        !          1604:     if ( ( buff == NULL ) || ( data_ref == NULL ) )
        !          1605:        return ( -1 );
        !          1606: 
        !          1607:     /*  Need to loop until compression output buffers are flushed  */
        !          1608: 
        !          1609:     do
        !          1610:     {
        !          1611:        z_err = deflate( &buff->zctrl, Z_FINISH );
        !          1612:        if ( z_err == Z_OK ) {
        !          1613:            /*  In this case Z_OK means more buffer space needed  */
        !          1614: 
        !          1615:            if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
        !          1616:                return ( -1 );
        !          1617:        }
        !          1618:     }
        !          1619:     while ( z_err == Z_OK );
        !          1620: 
        !          1621:     /*  If the compression state is not Z_STREAM_END, some error occurred  */
        !          1622: 
        !          1623:     if ( z_err == Z_STREAM_END ) {
        !          1624: 
        !          1625:        /*  Need to append the gzip data trailer  */
        !          1626: 
        !          1627:        if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
        !          1628:            if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
        !          1629:                return ( -1 );
        !          1630:        }
        !          1631: 
        !          1632:        /*
        !          1633:        **  For whatever reason, the CRC and length data are pushed out
        !          1634:        **  in reverse byte order.  So a memcpy can't be used here.
        !          1635:        */
        !          1636: 
        !          1637:        append_reverse_ulong( buff, buff->crc );
        !          1638:        append_reverse_ulong( buff, buff->zctrl.total_in );
        !          1639: 
        !          1640:        zlgth = buff->zctrl.next_out - buff->zbuff;
        !          1641:        *data_ref = (char *)buff->zbuff;
        !          1642:     }
        !          1643: 
        !          1644:     else {
        !          1645:        xmlChar msg[500];
        !          1646:        xmlStrPrintf(msg, 500,
        !          1647:                    (const xmlChar *) "xmlZMemBuffGetContent:  %s - %d\n",
        !          1648:                    "Error flushing zlib buffers.  Error code", z_err );
        !          1649:        xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          1650:     }
        !          1651: 
        !          1652:     return ( zlgth );
        !          1653: }
        !          1654: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1655: #endif  /*  HAVE_ZLIB_H  */
        !          1656: 
        !          1657: #ifdef LIBXML_OUTPUT_ENABLED
        !          1658: /**
        !          1659:  * xmlFreeHTTPWriteCtxt
        !          1660:  * @ctxt:  Context to cleanup
        !          1661:  *
        !          1662:  * Free allocated memory and reclaim system resources.
        !          1663:  *
        !          1664:  * No return value.
        !          1665:  */
        !          1666: static void
        !          1667: xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
        !          1668: {
        !          1669:     if ( ctxt->uri != NULL )
        !          1670:        xmlFree( ctxt->uri );
        !          1671: 
        !          1672:     if ( ctxt->doc_buff != NULL ) {
        !          1673: 
        !          1674: #ifdef HAVE_ZLIB_H
        !          1675:        if ( ctxt->compression > 0 ) {
        !          1676:            xmlFreeZMemBuff( ctxt->doc_buff );
        !          1677:        }
        !          1678:        else
        !          1679: #endif
        !          1680:        {
        !          1681:            xmlOutputBufferClose( ctxt->doc_buff );
        !          1682:        }
        !          1683:     }
        !          1684: 
        !          1685:     xmlFree( ctxt );
        !          1686:     return;
        !          1687: }
        !          1688: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1689: 
        !          1690: 
        !          1691: /**
        !          1692:  * xmlIOHTTPMatch:
        !          1693:  * @filename:  the URI for matching
        !          1694:  *
        !          1695:  * check if the URI matches an HTTP one
        !          1696:  *
        !          1697:  * Returns 1 if matches, 0 otherwise
        !          1698:  */
        !          1699: int
        !          1700: xmlIOHTTPMatch (const char *filename) {
        !          1701:     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
        !          1702:        return(1);
        !          1703:     return(0);
        !          1704: }
        !          1705: 
        !          1706: /**
        !          1707:  * xmlIOHTTPOpen:
        !          1708:  * @filename:  the URI for matching
        !          1709:  *
        !          1710:  * open an HTTP I/O channel
        !          1711:  *
        !          1712:  * Returns an I/O context or NULL in case of error
        !          1713:  */
        !          1714: void *
        !          1715: xmlIOHTTPOpen (const char *filename) {
        !          1716:     return(xmlNanoHTTPOpen(filename, NULL));
        !          1717: }
        !          1718: 
        !          1719: #ifdef LIBXML_OUTPUT_ENABLED
        !          1720: /**
        !          1721:  * xmlIOHTTPOpenW:
        !          1722:  * @post_uri:  The destination URI for the document
        !          1723:  * @compression:  The compression desired for the document.
        !          1724:  *
        !          1725:  * Open a temporary buffer to collect the document for a subsequent HTTP POST
        !          1726:  * request.  Non-static as is called from the output buffer creation routine.
        !          1727:  *
        !          1728:  * Returns an I/O context or NULL in case of error.
        !          1729:  */
        !          1730: 
        !          1731: void *
        !          1732: xmlIOHTTPOpenW(const char *post_uri, int compression)
        !          1733: {
        !          1734: 
        !          1735:     xmlIOHTTPWriteCtxtPtr ctxt = NULL;
        !          1736: 
        !          1737:     if (post_uri == NULL)
        !          1738:         return (NULL);
        !          1739: 
        !          1740:     ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
        !          1741:     if (ctxt == NULL) {
        !          1742:        xmlIOErrMemory("creating HTTP output context");
        !          1743:         return (NULL);
        !          1744:     }
        !          1745: 
        !          1746:     (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
        !          1747: 
        !          1748:     ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
        !          1749:     if (ctxt->uri == NULL) {
        !          1750:        xmlIOErrMemory("copying URI");
        !          1751:         xmlFreeHTTPWriteCtxt(ctxt);
        !          1752:         return (NULL);
        !          1753:     }
        !          1754: 
        !          1755:     /*
        !          1756:      * **  Since the document length is required for an HTTP post,
        !          1757:      * **  need to put the document into a buffer.  A memory buffer
        !          1758:      * **  is being used to avoid pushing the data to disk and back.
        !          1759:      */
        !          1760: 
        !          1761: #ifdef HAVE_ZLIB_H
        !          1762:     if ((compression > 0) && (compression <= 9)) {
        !          1763: 
        !          1764:         ctxt->compression = compression;
        !          1765:         ctxt->doc_buff = xmlCreateZMemBuff(compression);
        !          1766:     } else
        !          1767: #endif
        !          1768:     {
        !          1769:         /*  Any character conversions should have been done before this  */
        !          1770: 
        !          1771:         ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
        !          1772:     }
        !          1773: 
        !          1774:     if (ctxt->doc_buff == NULL) {
        !          1775:         xmlFreeHTTPWriteCtxt(ctxt);
        !          1776:         ctxt = NULL;
        !          1777:     }
        !          1778: 
        !          1779:     return (ctxt);
        !          1780: }
        !          1781: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1782: 
        !          1783: #ifdef LIBXML_OUTPUT_ENABLED
        !          1784: /**
        !          1785:  * xmlIOHTTPDfltOpenW
        !          1786:  * @post_uri:  The destination URI for this document.
        !          1787:  *
        !          1788:  * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent
        !          1789:  * HTTP post command.  This function should generally not be used as
        !          1790:  * the open callback is short circuited in xmlOutputBufferCreateFile.
        !          1791:  *
        !          1792:  * Returns a pointer to the new IO context.
        !          1793:  */
        !          1794: static void *
        !          1795: xmlIOHTTPDfltOpenW( const char * post_uri ) {
        !          1796:     return ( xmlIOHTTPOpenW( post_uri, 0 ) );
        !          1797: }
        !          1798: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1799: 
        !          1800: /**
        !          1801:  * xmlIOHTTPRead:
        !          1802:  * @context:  the I/O context
        !          1803:  * @buffer:  where to drop data
        !          1804:  * @len:  number of bytes to write
        !          1805:  *
        !          1806:  * Read @len bytes to @buffer from the I/O channel.
        !          1807:  *
        !          1808:  * Returns the number of bytes written
        !          1809:  */
        !          1810: int
        !          1811: xmlIOHTTPRead(void * context, char * buffer, int len) {
        !          1812:     if ((buffer == NULL) || (len < 0)) return(-1);
        !          1813:     return(xmlNanoHTTPRead(context, &buffer[0], len));
        !          1814: }
        !          1815: 
        !          1816: #ifdef LIBXML_OUTPUT_ENABLED
        !          1817: /**
        !          1818:  * xmlIOHTTPWrite
        !          1819:  * @context:  previously opened writing context
        !          1820:  * @buffer:   data to output to temporary buffer
        !          1821:  * @len:      bytes to output
        !          1822:  *
        !          1823:  * Collect data from memory buffer into a temporary file for later
        !          1824:  * processing.
        !          1825:  *
        !          1826:  * Returns number of bytes written.
        !          1827:  */
        !          1828: 
        !          1829: static int
        !          1830: xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
        !          1831: 
        !          1832:     xmlIOHTTPWriteCtxtPtr      ctxt = context;
        !          1833: 
        !          1834:     if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
        !          1835:        return ( -1 );
        !          1836: 
        !          1837:     if ( len > 0 ) {
        !          1838: 
        !          1839:        /*  Use gzwrite or fwrite as previously setup in the open call  */
        !          1840: 
        !          1841: #ifdef HAVE_ZLIB_H
        !          1842:        if ( ctxt->compression > 0 )
        !          1843:            len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
        !          1844: 
        !          1845:        else
        !          1846: #endif
        !          1847:            len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
        !          1848: 
        !          1849:        if ( len < 0 ) {
        !          1850:            xmlChar msg[500];
        !          1851:            xmlStrPrintf(msg, 500,
        !          1852:                        (const xmlChar *) "xmlIOHTTPWrite:  %s\n%s '%s'.\n",
        !          1853:                        "Error appending to internal buffer.",
        !          1854:                        "Error sending document to URI",
        !          1855:                        ctxt->uri );
        !          1856:            xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          1857:        }
        !          1858:     }
        !          1859: 
        !          1860:     return ( len );
        !          1861: }
        !          1862: #endif /* LIBXML_OUTPUT_ENABLED */
        !          1863: 
        !          1864: 
        !          1865: /**
        !          1866:  * xmlIOHTTPClose:
        !          1867:  * @context:  the I/O context
        !          1868:  *
        !          1869:  * Close an HTTP I/O channel
        !          1870:  *
        !          1871:  * Returns 0
        !          1872:  */
        !          1873: int
        !          1874: xmlIOHTTPClose (void * context) {
        !          1875:     xmlNanoHTTPClose(context);
        !          1876:     return 0;
        !          1877: }
        !          1878: 
        !          1879: #ifdef LIBXML_OUTPUT_ENABLED
        !          1880: /**
        !          1881:  * xmlIOHTTCloseWrite
        !          1882:  * @context:  The I/O context
        !          1883:  * @http_mthd: The HTTP method to be used when sending the data
        !          1884:  *
        !          1885:  * Close the transmit HTTP I/O channel and actually send the data.
        !          1886:  */
        !          1887: static int
        !          1888: xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
        !          1889: 
        !          1890:     int                                close_rc = -1;
        !          1891:     int                                http_rtn = 0;
        !          1892:     int                                content_lgth = 0;
        !          1893:     xmlIOHTTPWriteCtxtPtr      ctxt = context;
        !          1894: 
        !          1895:     char *                     http_content = NULL;
        !          1896:     char *                     content_encoding = NULL;
        !          1897:     char *                     content_type = (char *) "text/xml";
        !          1898:     void *                     http_ctxt = NULL;
        !          1899: 
        !          1900:     if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
        !          1901:        return ( -1 );
        !          1902: 
        !          1903:     /*  Retrieve the content from the appropriate buffer  */
        !          1904: 
        !          1905: #ifdef HAVE_ZLIB_H
        !          1906: 
        !          1907:     if ( ctxt->compression > 0 ) {
        !          1908:        content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
        !          1909:        content_encoding = (char *) "Content-Encoding: gzip";
        !          1910:     }
        !          1911:     else
        !          1912: #endif
        !          1913:     {
        !          1914:        /*  Pull the data out of the memory output buffer  */
        !          1915: 
        !          1916:        xmlOutputBufferPtr      dctxt = ctxt->doc_buff;
        !          1917:        http_content = (char *)dctxt->buffer->content;
        !          1918:        content_lgth = dctxt->buffer->use;
        !          1919:     }
        !          1920: 
        !          1921:     if ( http_content == NULL ) {
        !          1922:        xmlChar msg[500];
        !          1923:        xmlStrPrintf(msg, 500,
        !          1924:                     (const xmlChar *) "xmlIOHTTPCloseWrite:  %s '%s' %s '%s'.\n",
        !          1925:                     "Error retrieving content.\nUnable to",
        !          1926:                     http_mthd, "data to URI", ctxt->uri );
        !          1927:        xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          1928:     }
        !          1929: 
        !          1930:     else {
        !          1931: 
        !          1932:        http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
        !          1933:                                        &content_type, content_encoding,
        !          1934:                                        content_lgth );
        !          1935: 
        !          1936:        if ( http_ctxt != NULL ) {
        !          1937: #ifdef DEBUG_HTTP
        !          1938:            /*  If testing/debugging - dump reply with request content  */
        !          1939: 
        !          1940:            FILE *      tst_file = NULL;
        !          1941:            char        buffer[ 4096 ];
        !          1942:            char *      dump_name = NULL;
        !          1943:            int         avail;
        !          1944: 
        !          1945:            xmlGenericError( xmlGenericErrorContext,
        !          1946:                        "xmlNanoHTTPCloseWrite:  HTTP %s to\n%s returned %d.\n",
        !          1947:                        http_mthd, ctxt->uri,
        !          1948:                        xmlNanoHTTPReturnCode( http_ctxt ) );
        !          1949: 
        !          1950:            /*
        !          1951:            **  Since either content or reply may be gzipped,
        !          1952:            **  dump them to separate files instead of the
        !          1953:            **  standard error context.
        !          1954:            */
        !          1955: 
        !          1956:            dump_name = tempnam( NULL, "lxml" );
        !          1957:            if ( dump_name != NULL ) {
        !          1958:                (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
        !          1959: 
        !          1960:                tst_file = fopen( buffer, "wb" );
        !          1961:                if ( tst_file != NULL ) {
        !          1962:                    xmlGenericError( xmlGenericErrorContext,
        !          1963:                        "Transmitted content saved in file:  %s\n", buffer );
        !          1964: 
        !          1965:                    fwrite( http_content, sizeof( char ),
        !          1966:                                        content_lgth, tst_file );
        !          1967:                    fclose( tst_file );
        !          1968:                }
        !          1969: 
        !          1970:                (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
        !          1971:                tst_file = fopen( buffer, "wb" );
        !          1972:                if ( tst_file != NULL ) {
        !          1973:                    xmlGenericError( xmlGenericErrorContext,
        !          1974:                        "Reply content saved in file:  %s\n", buffer );
        !          1975: 
        !          1976: 
        !          1977:                    while ( (avail = xmlNanoHTTPRead( http_ctxt,
        !          1978:                                        buffer, sizeof( buffer ) )) > 0 ) {
        !          1979: 
        !          1980:                        fwrite( buffer, sizeof( char ), avail, tst_file );
        !          1981:                    }
        !          1982: 
        !          1983:                    fclose( tst_file );
        !          1984:                }
        !          1985: 
        !          1986:                free( dump_name );
        !          1987:            }
        !          1988: #endif  /*  DEBUG_HTTP  */
        !          1989: 
        !          1990:            http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
        !          1991:            if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
        !          1992:                close_rc = 0;
        !          1993:            else {
        !          1994:                 xmlChar msg[500];
        !          1995:                 xmlStrPrintf(msg, 500,
        !          1996:     (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
        !          1997:                            http_mthd, content_lgth,
        !          1998:                            "bytes to URI", ctxt->uri,
        !          1999:                            "failed.  HTTP return code:", http_rtn );
        !          2000:                xmlIOErr(XML_IO_WRITE, (const char *) msg);
        !          2001:             }
        !          2002: 
        !          2003:            xmlNanoHTTPClose( http_ctxt );
        !          2004:            xmlFree( content_type );
        !          2005:        }
        !          2006:     }
        !          2007: 
        !          2008:     /*  Final cleanups  */
        !          2009: 
        !          2010:     xmlFreeHTTPWriteCtxt( ctxt );
        !          2011: 
        !          2012:     return ( close_rc );
        !          2013: }
        !          2014: 
        !          2015: /**
        !          2016:  * xmlIOHTTPClosePut
        !          2017:  *
        !          2018:  * @context:  The I/O context
        !          2019:  *
        !          2020:  * Close the transmit HTTP I/O channel and actually send data using a PUT
        !          2021:  * HTTP method.
        !          2022:  */
        !          2023: static int
        !          2024: xmlIOHTTPClosePut( void * ctxt ) {
        !          2025:     return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
        !          2026: }
        !          2027: 
        !          2028: 
        !          2029: /**
        !          2030:  * xmlIOHTTPClosePost
        !          2031:  *
        !          2032:  * @context:  The I/O context
        !          2033:  *
        !          2034:  * Close the transmit HTTP I/O channel and actually send data using a POST
        !          2035:  * HTTP method.
        !          2036:  */
        !          2037: static int
        !          2038: xmlIOHTTPClosePost( void * ctxt ) {
        !          2039:     return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
        !          2040: }
        !          2041: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2042: 
        !          2043: #endif /* LIBXML_HTTP_ENABLED */
        !          2044: 
        !          2045: #ifdef LIBXML_FTP_ENABLED
        !          2046: /************************************************************************
        !          2047:  *                                                                     *
        !          2048:  *                     I/O for FTP file accesses                       *
        !          2049:  *                                                                     *
        !          2050:  ************************************************************************/
        !          2051: /**
        !          2052:  * xmlIOFTPMatch:
        !          2053:  * @filename:  the URI for matching
        !          2054:  *
        !          2055:  * check if the URI matches an FTP one
        !          2056:  *
        !          2057:  * Returns 1 if matches, 0 otherwise
        !          2058:  */
        !          2059: int
        !          2060: xmlIOFTPMatch (const char *filename) {
        !          2061:     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
        !          2062:        return(1);
        !          2063:     return(0);
        !          2064: }
        !          2065: 
        !          2066: /**
        !          2067:  * xmlIOFTPOpen:
        !          2068:  * @filename:  the URI for matching
        !          2069:  *
        !          2070:  * open an FTP I/O channel
        !          2071:  *
        !          2072:  * Returns an I/O context or NULL in case of error
        !          2073:  */
        !          2074: void *
        !          2075: xmlIOFTPOpen (const char *filename) {
        !          2076:     return(xmlNanoFTPOpen(filename));
        !          2077: }
        !          2078: 
        !          2079: /**
        !          2080:  * xmlIOFTPRead:
        !          2081:  * @context:  the I/O context
        !          2082:  * @buffer:  where to drop data
        !          2083:  * @len:  number of bytes to write
        !          2084:  *
        !          2085:  * Read @len bytes to @buffer from the I/O channel.
        !          2086:  *
        !          2087:  * Returns the number of bytes written
        !          2088:  */
        !          2089: int
        !          2090: xmlIOFTPRead(void * context, char * buffer, int len) {
        !          2091:     if ((buffer == NULL) || (len < 0)) return(-1);
        !          2092:     return(xmlNanoFTPRead(context, &buffer[0], len));
        !          2093: }
        !          2094: 
        !          2095: /**
        !          2096:  * xmlIOFTPClose:
        !          2097:  * @context:  the I/O context
        !          2098:  *
        !          2099:  * Close an FTP I/O channel
        !          2100:  *
        !          2101:  * Returns 0
        !          2102:  */
        !          2103: int
        !          2104: xmlIOFTPClose (void * context) {
        !          2105:     return ( xmlNanoFTPClose(context) );
        !          2106: }
        !          2107: #endif /* LIBXML_FTP_ENABLED */
        !          2108: 
        !          2109: 
        !          2110: /**
        !          2111:  * xmlRegisterInputCallbacks:
        !          2112:  * @matchFunc:  the xmlInputMatchCallback
        !          2113:  * @openFunc:  the xmlInputOpenCallback
        !          2114:  * @readFunc:  the xmlInputReadCallback
        !          2115:  * @closeFunc:  the xmlInputCloseCallback
        !          2116:  *
        !          2117:  * Register a new set of I/O callback for handling parser input.
        !          2118:  *
        !          2119:  * Returns the registered handler number or -1 in case of error
        !          2120:  */
        !          2121: int
        !          2122: xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
        !          2123:        xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
        !          2124:        xmlInputCloseCallback closeFunc) {
        !          2125:     if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
        !          2126:        return(-1);
        !          2127:     }
        !          2128:     xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
        !          2129:     xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
        !          2130:     xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
        !          2131:     xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
        !          2132:     xmlInputCallbackInitialized = 1;
        !          2133:     return(xmlInputCallbackNr++);
        !          2134: }
        !          2135: 
        !          2136: #ifdef LIBXML_OUTPUT_ENABLED
        !          2137: /**
        !          2138:  * xmlRegisterOutputCallbacks:
        !          2139:  * @matchFunc:  the xmlOutputMatchCallback
        !          2140:  * @openFunc:  the xmlOutputOpenCallback
        !          2141:  * @writeFunc:  the xmlOutputWriteCallback
        !          2142:  * @closeFunc:  the xmlOutputCloseCallback
        !          2143:  *
        !          2144:  * Register a new set of I/O callback for handling output.
        !          2145:  *
        !          2146:  * Returns the registered handler number or -1 in case of error
        !          2147:  */
        !          2148: int
        !          2149: xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
        !          2150:        xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
        !          2151:        xmlOutputCloseCallback closeFunc) {
        !          2152:     if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
        !          2153:        return(-1);
        !          2154:     }
        !          2155:     xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
        !          2156:     xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
        !          2157:     xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
        !          2158:     xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
        !          2159:     xmlOutputCallbackInitialized = 1;
        !          2160:     return(xmlOutputCallbackNr++);
        !          2161: }
        !          2162: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2163: 
        !          2164: /**
        !          2165:  * xmlRegisterDefaultInputCallbacks:
        !          2166:  *
        !          2167:  * Registers the default compiled-in I/O handlers.
        !          2168:  */
        !          2169: void
        !          2170: xmlRegisterDefaultInputCallbacks(void) {
        !          2171:     if (xmlInputCallbackInitialized)
        !          2172:        return;
        !          2173: 
        !          2174: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !          2175:     xmlInitPlatformSpecificIo();
        !          2176: #endif
        !          2177: 
        !          2178:     xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
        !          2179:                              xmlFileRead, xmlFileClose);
        !          2180: #ifdef HAVE_ZLIB_H
        !          2181:     xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
        !          2182:                              xmlGzfileRead, xmlGzfileClose);
        !          2183: #endif /* HAVE_ZLIB_H */
        !          2184: 
        !          2185: #ifdef LIBXML_HTTP_ENABLED
        !          2186:     xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
        !          2187:                              xmlIOHTTPRead, xmlIOHTTPClose);
        !          2188: #endif /* LIBXML_HTTP_ENABLED */
        !          2189: 
        !          2190: #ifdef LIBXML_FTP_ENABLED
        !          2191:     xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
        !          2192:                              xmlIOFTPRead, xmlIOFTPClose);
        !          2193: #endif /* LIBXML_FTP_ENABLED */
        !          2194:     xmlInputCallbackInitialized = 1;
        !          2195: }
        !          2196: 
        !          2197: #ifdef LIBXML_OUTPUT_ENABLED
        !          2198: /**
        !          2199:  * xmlRegisterDefaultOutputCallbacks:
        !          2200:  *
        !          2201:  * Registers the default compiled-in I/O handlers.
        !          2202:  */
        !          2203: void
        !          2204: xmlRegisterDefaultOutputCallbacks (void) {
        !          2205:     if (xmlOutputCallbackInitialized)
        !          2206:        return;
        !          2207: 
        !          2208: #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
        !          2209:     xmlInitPlatformSpecificIo();
        !          2210: #endif
        !          2211: 
        !          2212:     xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
        !          2213:                              xmlFileWrite, xmlFileClose);
        !          2214: 
        !          2215: #ifdef LIBXML_HTTP_ENABLED
        !          2216:     xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
        !          2217:                               xmlIOHTTPWrite, xmlIOHTTPClosePut);
        !          2218: #endif
        !          2219: 
        !          2220: /*********************************
        !          2221:  No way a-priori to distinguish between gzipped files from
        !          2222:  uncompressed ones except opening if existing then closing
        !          2223:  and saving with same compression ratio ... a pain.
        !          2224: 
        !          2225: #ifdef HAVE_ZLIB_H
        !          2226:     xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
        !          2227:                               xmlGzfileWrite, xmlGzfileClose);
        !          2228: #endif
        !          2229: 
        !          2230:  Nor FTP PUT ....
        !          2231: #ifdef LIBXML_FTP_ENABLED
        !          2232:     xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
        !          2233:                               xmlIOFTPWrite, xmlIOFTPClose);
        !          2234: #endif
        !          2235:  **********************************/
        !          2236:     xmlOutputCallbackInitialized = 1;
        !          2237: }
        !          2238: 
        !          2239: #ifdef LIBXML_HTTP_ENABLED
        !          2240: /**
        !          2241:  * xmlRegisterHTTPPostCallbacks:
        !          2242:  *
        !          2243:  * By default, libxml submits HTTP output requests using the "PUT" method.
        !          2244:  * Calling this method changes the HTTP output method to use the "POST"
        !          2245:  * method instead.
        !          2246:  *
        !          2247:  */
        !          2248: void
        !          2249: xmlRegisterHTTPPostCallbacks( void ) {
        !          2250: 
        !          2251:     /*  Register defaults if not done previously  */
        !          2252: 
        !          2253:     if ( xmlOutputCallbackInitialized == 0 )
        !          2254:        xmlRegisterDefaultOutputCallbacks( );
        !          2255: 
        !          2256:     xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
        !          2257:                               xmlIOHTTPWrite, xmlIOHTTPClosePost);
        !          2258:     return;
        !          2259: }
        !          2260: #endif
        !          2261: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2262: 
        !          2263: /**
        !          2264:  * xmlAllocParserInputBuffer:
        !          2265:  * @enc:  the charset encoding if known
        !          2266:  *
        !          2267:  * Create a buffered parser input for progressive parsing
        !          2268:  *
        !          2269:  * Returns the new parser input or NULL
        !          2270:  */
        !          2271: xmlParserInputBufferPtr
        !          2272: xmlAllocParserInputBuffer(xmlCharEncoding enc) {
        !          2273:     xmlParserInputBufferPtr ret;
        !          2274: 
        !          2275:     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
        !          2276:     if (ret == NULL) {
        !          2277:        xmlIOErrMemory("creating input buffer");
        !          2278:        return(NULL);
        !          2279:     }
        !          2280:     memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
        !          2281:     ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
        !          2282:     if (ret->buffer == NULL) {
        !          2283:         xmlFree(ret);
        !          2284:        return(NULL);
        !          2285:     }
        !          2286:     ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
        !          2287:     ret->encoder = xmlGetCharEncodingHandler(enc);
        !          2288:     if (ret->encoder != NULL)
        !          2289:         ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
        !          2290:     else
        !          2291:         ret->raw = NULL;
        !          2292:     ret->readcallback = NULL;
        !          2293:     ret->closecallback = NULL;
        !          2294:     ret->context = NULL;
        !          2295:     ret->compressed = -1;
        !          2296:     ret->rawconsumed = 0;
        !          2297: 
        !          2298:     return(ret);
        !          2299: }
        !          2300: 
        !          2301: #ifdef LIBXML_OUTPUT_ENABLED
        !          2302: /**
        !          2303:  * xmlAllocOutputBuffer:
        !          2304:  * @encoder:  the encoding converter or NULL
        !          2305:  *
        !          2306:  * Create a buffered parser output
        !          2307:  *
        !          2308:  * Returns the new parser output or NULL
        !          2309:  */
        !          2310: xmlOutputBufferPtr
        !          2311: xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
        !          2312:     xmlOutputBufferPtr ret;
        !          2313: 
        !          2314:     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
        !          2315:     if (ret == NULL) {
        !          2316:        xmlIOErrMemory("creating output buffer");
        !          2317:        return(NULL);
        !          2318:     }
        !          2319:     memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
        !          2320:     ret->buffer = xmlBufferCreate();
        !          2321:     if (ret->buffer == NULL) {
        !          2322:         xmlFree(ret);
        !          2323:        return(NULL);
        !          2324:     }
        !          2325: 
        !          2326:     /* try to avoid a performance problem with Windows realloc() */
        !          2327:     if (ret->buffer->alloc == XML_BUFFER_ALLOC_EXACT)
        !          2328:         ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
        !          2329: 
        !          2330:     ret->encoder = encoder;
        !          2331:     if (encoder != NULL) {
        !          2332:         ret->conv = xmlBufferCreateSize(4000);
        !          2333:        if (ret->conv == NULL) {
        !          2334:            xmlFree(ret);
        !          2335:            return(NULL);
        !          2336:        }
        !          2337: 
        !          2338:        /*
        !          2339:         * This call is designed to initiate the encoder state
        !          2340:         */
        !          2341:        xmlCharEncOutFunc(encoder, ret->conv, NULL);
        !          2342:     } else
        !          2343:         ret->conv = NULL;
        !          2344:     ret->writecallback = NULL;
        !          2345:     ret->closecallback = NULL;
        !          2346:     ret->context = NULL;
        !          2347:     ret->written = 0;
        !          2348: 
        !          2349:     return(ret);
        !          2350: }
        !          2351: 
        !          2352: /**
        !          2353:  * xmlAllocOutputBufferInternal:
        !          2354:  * @encoder:  the encoding converter or NULL
        !          2355:  *
        !          2356:  * Create a buffered parser output
        !          2357:  *
        !          2358:  * Returns the new parser output or NULL
        !          2359:  */
        !          2360: xmlOutputBufferPtr
        !          2361: xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
        !          2362:     xmlOutputBufferPtr ret;
        !          2363: 
        !          2364:     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
        !          2365:     if (ret == NULL) {
        !          2366:        xmlIOErrMemory("creating output buffer");
        !          2367:        return(NULL);
        !          2368:     }
        !          2369:     memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
        !          2370:     ret->buffer = xmlBufferCreate();
        !          2371:     if (ret->buffer == NULL) {
        !          2372:         xmlFree(ret);
        !          2373:        return(NULL);
        !          2374:     }
        !          2375: 
        !          2376: 
        !          2377:     /*
        !          2378:      * For conversion buffers we use the special IO handling
        !          2379:      * We don't do that from the exported API to avoid confusing
        !          2380:      * user's code.
        !          2381:      */
        !          2382:     ret->buffer->alloc = XML_BUFFER_ALLOC_IO;
        !          2383:     ret->buffer->contentIO = ret->buffer->content;
        !          2384: 
        !          2385:     ret->encoder = encoder;
        !          2386:     if (encoder != NULL) {
        !          2387:         ret->conv = xmlBufferCreateSize(4000);
        !          2388:        if (ret->conv == NULL) {
        !          2389:            xmlFree(ret);
        !          2390:            return(NULL);
        !          2391:        }
        !          2392: 
        !          2393:        /*
        !          2394:         * This call is designed to initiate the encoder state
        !          2395:         */
        !          2396:        xmlCharEncOutFunc(encoder, ret->conv, NULL);
        !          2397:     } else
        !          2398:         ret->conv = NULL;
        !          2399:     ret->writecallback = NULL;
        !          2400:     ret->closecallback = NULL;
        !          2401:     ret->context = NULL;
        !          2402:     ret->written = 0;
        !          2403: 
        !          2404:     return(ret);
        !          2405: }
        !          2406: 
        !          2407: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2408: 
        !          2409: /**
        !          2410:  * xmlFreeParserInputBuffer:
        !          2411:  * @in:  a buffered parser input
        !          2412:  *
        !          2413:  * Free up the memory used by a buffered parser input
        !          2414:  */
        !          2415: void
        !          2416: xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
        !          2417:     if (in == NULL) return;
        !          2418: 
        !          2419:     if (in->raw) {
        !          2420:         xmlBufferFree(in->raw);
        !          2421:        in->raw = NULL;
        !          2422:     }
        !          2423:     if (in->encoder != NULL) {
        !          2424:         xmlCharEncCloseFunc(in->encoder);
        !          2425:     }
        !          2426:     if (in->closecallback != NULL) {
        !          2427:        in->closecallback(in->context);
        !          2428:     }
        !          2429:     if (in->buffer != NULL) {
        !          2430:         xmlBufferFree(in->buffer);
        !          2431:        in->buffer = NULL;
        !          2432:     }
        !          2433: 
        !          2434:     xmlFree(in);
        !          2435: }
        !          2436: 
        !          2437: #ifdef LIBXML_OUTPUT_ENABLED
        !          2438: /**
        !          2439:  * xmlOutputBufferClose:
        !          2440:  * @out:  a buffered output
        !          2441:  *
        !          2442:  * flushes and close the output I/O channel
        !          2443:  * and free up all the associated resources
        !          2444:  *
        !          2445:  * Returns the number of byte written or -1 in case of error.
        !          2446:  */
        !          2447: int
        !          2448: xmlOutputBufferClose(xmlOutputBufferPtr out)
        !          2449: {
        !          2450:     int written;
        !          2451:     int err_rc = 0;
        !          2452: 
        !          2453:     if (out == NULL)
        !          2454:         return (-1);
        !          2455:     if (out->writecallback != NULL)
        !          2456:         xmlOutputBufferFlush(out);
        !          2457:     if (out->closecallback != NULL) {
        !          2458:         err_rc = out->closecallback(out->context);
        !          2459:     }
        !          2460:     written = out->written;
        !          2461:     if (out->conv) {
        !          2462:         xmlBufferFree(out->conv);
        !          2463:         out->conv = NULL;
        !          2464:     }
        !          2465:     if (out->encoder != NULL) {
        !          2466:         xmlCharEncCloseFunc(out->encoder);
        !          2467:     }
        !          2468:     if (out->buffer != NULL) {
        !          2469:         xmlBufferFree(out->buffer);
        !          2470:         out->buffer = NULL;
        !          2471:     }
        !          2472: 
        !          2473:     if (out->error)
        !          2474:         err_rc = -1;
        !          2475:     xmlFree(out);
        !          2476:     return ((err_rc == 0) ? written : err_rc);
        !          2477: }
        !          2478: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2479: 
        !          2480: xmlParserInputBufferPtr
        !          2481: __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
        !          2482:     xmlParserInputBufferPtr ret;
        !          2483:     int i = 0;
        !          2484:     void *context = NULL;
        !          2485: 
        !          2486:     if (xmlInputCallbackInitialized == 0)
        !          2487:        xmlRegisterDefaultInputCallbacks();
        !          2488: 
        !          2489:     if (URI == NULL) return(NULL);
        !          2490: 
        !          2491:     /*
        !          2492:      * Try to find one of the input accept method accepting that scheme
        !          2493:      * Go in reverse to give precedence to user defined handlers.
        !          2494:      */
        !          2495:     if (context == NULL) {
        !          2496:        for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
        !          2497:            if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
        !          2498:                (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
        !          2499:                context = xmlInputCallbackTable[i].opencallback(URI);
        !          2500:                if (context != NULL) {
        !          2501:                    break;
        !          2502:                }
        !          2503:            }
        !          2504:        }
        !          2505:     }
        !          2506:     if (context == NULL) {
        !          2507:        return(NULL);
        !          2508:     }
        !          2509: 
        !          2510:     /*
        !          2511:      * Allocate the Input buffer front-end.
        !          2512:      */
        !          2513:     ret = xmlAllocParserInputBuffer(enc);
        !          2514:     if (ret != NULL) {
        !          2515:        ret->context = context;
        !          2516:        ret->readcallback = xmlInputCallbackTable[i].readcallback;
        !          2517:        ret->closecallback = xmlInputCallbackTable[i].closecallback;
        !          2518: #ifdef HAVE_ZLIB_H
        !          2519:        if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
        !          2520:                (strcmp(URI, "-") != 0)) {
        !          2521: #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
        !          2522:             ret->compressed = !gzdirect(context);
        !          2523: #else
        !          2524:            if (((z_stream *)context)->avail_in > 4) {
        !          2525:                char *cptr, buff4[4];
        !          2526:                cptr = (char *) ((z_stream *)context)->next_in;
        !          2527:                if (gzread(context, buff4, 4) == 4) {
        !          2528:                    if (strncmp(buff4, cptr, 4) == 0)
        !          2529:                        ret->compressed = 0;
        !          2530:                    else
        !          2531:                        ret->compressed = 1;
        !          2532:                    gzrewind(context);
        !          2533:                }
        !          2534:            }
        !          2535: #endif
        !          2536:        }
        !          2537: #endif
        !          2538:     }
        !          2539:     else
        !          2540:       xmlInputCallbackTable[i].closecallback (context);
        !          2541: 
        !          2542:     return(ret);
        !          2543: }
        !          2544: 
        !          2545: /**
        !          2546:  * xmlParserInputBufferCreateFilename:
        !          2547:  * @URI:  a C string containing the URI or filename
        !          2548:  * @enc:  the charset encoding if known
        !          2549:  *
        !          2550:  * Create a buffered parser input for the progressive parsing of a file
        !          2551:  * If filename is "-' then we use stdin as the input.
        !          2552:  * Automatic support for ZLIB/Compress compressed document is provided
        !          2553:  * by default if found at compile-time.
        !          2554:  * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
        !          2555:  *
        !          2556:  * Returns the new parser input or NULL
        !          2557:  */
        !          2558: xmlParserInputBufferPtr
        !          2559: xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
        !          2560:     if ((xmlParserInputBufferCreateFilenameValue)) {
        !          2561:                return xmlParserInputBufferCreateFilenameValue(URI, enc);
        !          2562:        }
        !          2563:        return __xmlParserInputBufferCreateFilename(URI, enc);
        !          2564: }
        !          2565: 
        !          2566: #ifdef LIBXML_OUTPUT_ENABLED
        !          2567: xmlOutputBufferPtr
        !          2568: __xmlOutputBufferCreateFilename(const char *URI,
        !          2569:                               xmlCharEncodingHandlerPtr encoder,
        !          2570:                               int compression ATTRIBUTE_UNUSED) {
        !          2571:     xmlOutputBufferPtr ret;
        !          2572:     xmlURIPtr puri;
        !          2573:     int i = 0;
        !          2574:     void *context = NULL;
        !          2575:     char *unescaped = NULL;
        !          2576: #ifdef HAVE_ZLIB_H
        !          2577:     int is_file_uri = 1;
        !          2578: #endif
        !          2579: 
        !          2580:     if (xmlOutputCallbackInitialized == 0)
        !          2581:        xmlRegisterDefaultOutputCallbacks();
        !          2582: 
        !          2583:     if (URI == NULL) return(NULL);
        !          2584: 
        !          2585:     puri = xmlParseURI(URI);
        !          2586:     if (puri != NULL) {
        !          2587: #ifdef HAVE_ZLIB_H
        !          2588:         if ((puri->scheme != NULL) &&
        !          2589:            (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
        !          2590:            is_file_uri = 0;
        !          2591: #endif
        !          2592:        /*
        !          2593:         * try to limit the damages of the URI unescaping code.
        !          2594:         */
        !          2595:        if ((puri->scheme == NULL) ||
        !          2596:            (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
        !          2597:            unescaped = xmlURIUnescapeString(URI, 0, NULL);
        !          2598:        xmlFreeURI(puri);
        !          2599:     }
        !          2600: 
        !          2601:     /*
        !          2602:      * Try to find one of the output accept method accepting that scheme
        !          2603:      * Go in reverse to give precedence to user defined handlers.
        !          2604:      * try with an unescaped version of the URI
        !          2605:      */
        !          2606:     if (unescaped != NULL) {
        !          2607: #ifdef HAVE_ZLIB_H
        !          2608:        if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
        !          2609:            context = xmlGzfileOpenW(unescaped, compression);
        !          2610:            if (context != NULL) {
        !          2611:                ret = xmlAllocOutputBufferInternal(encoder);
        !          2612:                if (ret != NULL) {
        !          2613:                    ret->context = context;
        !          2614:                    ret->writecallback = xmlGzfileWrite;
        !          2615:                    ret->closecallback = xmlGzfileClose;
        !          2616:                }
        !          2617:                xmlFree(unescaped);
        !          2618:                return(ret);
        !          2619:            }
        !          2620:        }
        !          2621: #endif
        !          2622:        for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
        !          2623:            if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
        !          2624:                (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
        !          2625: #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
        !          2626:                /*  Need to pass compression parameter into HTTP open calls  */
        !          2627:                if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
        !          2628:                    context = xmlIOHTTPOpenW(unescaped, compression);
        !          2629:                else
        !          2630: #endif
        !          2631:                    context = xmlOutputCallbackTable[i].opencallback(unescaped);
        !          2632:                if (context != NULL)
        !          2633:                    break;
        !          2634:            }
        !          2635:        }
        !          2636:        xmlFree(unescaped);
        !          2637:     }
        !          2638: 
        !          2639:     /*
        !          2640:      * If this failed try with a non-escaped URI this may be a strange
        !          2641:      * filename
        !          2642:      */
        !          2643:     if (context == NULL) {
        !          2644: #ifdef HAVE_ZLIB_H
        !          2645:        if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
        !          2646:            context = xmlGzfileOpenW(URI, compression);
        !          2647:            if (context != NULL) {
        !          2648:                ret = xmlAllocOutputBufferInternal(encoder);
        !          2649:                if (ret != NULL) {
        !          2650:                    ret->context = context;
        !          2651:                    ret->writecallback = xmlGzfileWrite;
        !          2652:                    ret->closecallback = xmlGzfileClose;
        !          2653:                }
        !          2654:                return(ret);
        !          2655:            }
        !          2656:        }
        !          2657: #endif
        !          2658:        for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
        !          2659:            if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
        !          2660:                (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
        !          2661: #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
        !          2662:                /*  Need to pass compression parameter into HTTP open calls  */
        !          2663:                if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
        !          2664:                    context = xmlIOHTTPOpenW(URI, compression);
        !          2665:                else
        !          2666: #endif
        !          2667:                    context = xmlOutputCallbackTable[i].opencallback(URI);
        !          2668:                if (context != NULL)
        !          2669:                    break;
        !          2670:            }
        !          2671:        }
        !          2672:     }
        !          2673: 
        !          2674:     if (context == NULL) {
        !          2675:        return(NULL);
        !          2676:     }
        !          2677: 
        !          2678:     /*
        !          2679:      * Allocate the Output buffer front-end.
        !          2680:      */
        !          2681:     ret = xmlAllocOutputBufferInternal(encoder);
        !          2682:     if (ret != NULL) {
        !          2683:        ret->context = context;
        !          2684:        ret->writecallback = xmlOutputCallbackTable[i].writecallback;
        !          2685:        ret->closecallback = xmlOutputCallbackTable[i].closecallback;
        !          2686:     }
        !          2687:     return(ret);
        !          2688: }
        !          2689: 
        !          2690: /**
        !          2691:  * xmlOutputBufferCreateFilename:
        !          2692:  * @URI:  a C string containing the URI or filename
        !          2693:  * @encoder:  the encoding converter or NULL
        !          2694:  * @compression:  the compression ration (0 none, 9 max).
        !          2695:  *
        !          2696:  * Create a buffered  output for the progressive saving of a file
        !          2697:  * If filename is "-' then we use stdout as the output.
        !          2698:  * Automatic support for ZLIB/Compress compressed document is provided
        !          2699:  * by default if found at compile-time.
        !          2700:  * TODO: currently if compression is set, the library only support
        !          2701:  *       writing to a local file.
        !          2702:  *
        !          2703:  * Returns the new output or NULL
        !          2704:  */
        !          2705: xmlOutputBufferPtr
        !          2706: xmlOutputBufferCreateFilename(const char *URI,
        !          2707:                               xmlCharEncodingHandlerPtr encoder,
        !          2708:                               int compression ATTRIBUTE_UNUSED) {
        !          2709:     if ((xmlOutputBufferCreateFilenameValue)) {
        !          2710:                return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
        !          2711:        }
        !          2712:        return __xmlOutputBufferCreateFilename(URI, encoder, compression);
        !          2713: }
        !          2714: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2715: 
        !          2716: /**
        !          2717:  * xmlParserInputBufferCreateFile:
        !          2718:  * @file:  a FILE*
        !          2719:  * @enc:  the charset encoding if known
        !          2720:  *
        !          2721:  * Create a buffered parser input for the progressive parsing of a FILE *
        !          2722:  * buffered C I/O
        !          2723:  *
        !          2724:  * Returns the new parser input or NULL
        !          2725:  */
        !          2726: xmlParserInputBufferPtr
        !          2727: xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
        !          2728:     xmlParserInputBufferPtr ret;
        !          2729: 
        !          2730:     if (xmlInputCallbackInitialized == 0)
        !          2731:        xmlRegisterDefaultInputCallbacks();
        !          2732: 
        !          2733:     if (file == NULL) return(NULL);
        !          2734: 
        !          2735:     ret = xmlAllocParserInputBuffer(enc);
        !          2736:     if (ret != NULL) {
        !          2737:         ret->context = file;
        !          2738:        ret->readcallback = xmlFileRead;
        !          2739:        ret->closecallback = xmlFileFlush;
        !          2740:     }
        !          2741: 
        !          2742:     return(ret);
        !          2743: }
        !          2744: 
        !          2745: #ifdef LIBXML_OUTPUT_ENABLED
        !          2746: /**
        !          2747:  * xmlOutputBufferCreateFile:
        !          2748:  * @file:  a FILE*
        !          2749:  * @encoder:  the encoding converter or NULL
        !          2750:  *
        !          2751:  * Create a buffered output for the progressive saving to a FILE *
        !          2752:  * buffered C I/O
        !          2753:  *
        !          2754:  * Returns the new parser output or NULL
        !          2755:  */
        !          2756: xmlOutputBufferPtr
        !          2757: xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
        !          2758:     xmlOutputBufferPtr ret;
        !          2759: 
        !          2760:     if (xmlOutputCallbackInitialized == 0)
        !          2761:        xmlRegisterDefaultOutputCallbacks();
        !          2762: 
        !          2763:     if (file == NULL) return(NULL);
        !          2764: 
        !          2765:     ret = xmlAllocOutputBufferInternal(encoder);
        !          2766:     if (ret != NULL) {
        !          2767:         ret->context = file;
        !          2768:        ret->writecallback = xmlFileWrite;
        !          2769:        ret->closecallback = xmlFileFlush;
        !          2770:     }
        !          2771: 
        !          2772:     return(ret);
        !          2773: }
        !          2774: 
        !          2775: /**
        !          2776:  * xmlOutputBufferCreateBuffer:
        !          2777:  * @buffer:  a xmlBufferPtr
        !          2778:  * @encoder:  the encoding converter or NULL
        !          2779:  *
        !          2780:  * Create a buffered output for the progressive saving to a xmlBuffer
        !          2781:  *
        !          2782:  * Returns the new parser output or NULL
        !          2783:  */
        !          2784: xmlOutputBufferPtr
        !          2785: xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
        !          2786:                             xmlCharEncodingHandlerPtr encoder) {
        !          2787:     xmlOutputBufferPtr ret;
        !          2788: 
        !          2789:     if (buffer == NULL) return(NULL);
        !          2790: 
        !          2791:     ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
        !          2792:                                   xmlBufferWrite,
        !          2793:                                   (xmlOutputCloseCallback)
        !          2794:                                   NULL, (void *) buffer, encoder);
        !          2795: 
        !          2796:     return(ret);
        !          2797: }
        !          2798: 
        !          2799: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2800: 
        !          2801: /**
        !          2802:  * xmlParserInputBufferCreateFd:
        !          2803:  * @fd:  a file descriptor number
        !          2804:  * @enc:  the charset encoding if known
        !          2805:  *
        !          2806:  * Create a buffered parser input for the progressive parsing for the input
        !          2807:  * from a file descriptor
        !          2808:  *
        !          2809:  * Returns the new parser input or NULL
        !          2810:  */
        !          2811: xmlParserInputBufferPtr
        !          2812: xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
        !          2813:     xmlParserInputBufferPtr ret;
        !          2814: 
        !          2815:     if (fd < 0) return(NULL);
        !          2816: 
        !          2817:     ret = xmlAllocParserInputBuffer(enc);
        !          2818:     if (ret != NULL) {
        !          2819:         ret->context = (void *) (long) fd;
        !          2820:        ret->readcallback = xmlFdRead;
        !          2821:        ret->closecallback = xmlFdClose;
        !          2822:     }
        !          2823: 
        !          2824:     return(ret);
        !          2825: }
        !          2826: 
        !          2827: /**
        !          2828:  * xmlParserInputBufferCreateMem:
        !          2829:  * @mem:  the memory input
        !          2830:  * @size:  the length of the memory block
        !          2831:  * @enc:  the charset encoding if known
        !          2832:  *
        !          2833:  * Create a buffered parser input for the progressive parsing for the input
        !          2834:  * from a memory area.
        !          2835:  *
        !          2836:  * Returns the new parser input or NULL
        !          2837:  */
        !          2838: xmlParserInputBufferPtr
        !          2839: xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
        !          2840:     xmlParserInputBufferPtr ret;
        !          2841:     int errcode;
        !          2842: 
        !          2843:     if (size <= 0) return(NULL);
        !          2844:     if (mem == NULL) return(NULL);
        !          2845: 
        !          2846:     ret = xmlAllocParserInputBuffer(enc);
        !          2847:     if (ret != NULL) {
        !          2848:         ret->context = (void *) mem;
        !          2849:        ret->readcallback = (xmlInputReadCallback) xmlNop;
        !          2850:        ret->closecallback = NULL;
        !          2851:        errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
        !          2852:        if (errcode != 0) {
        !          2853:            xmlFree(ret);
        !          2854:            return(NULL);
        !          2855:        }
        !          2856:     }
        !          2857: 
        !          2858:     return(ret);
        !          2859: }
        !          2860: 
        !          2861: /**
        !          2862:  * xmlParserInputBufferCreateStatic:
        !          2863:  * @mem:  the memory input
        !          2864:  * @size:  the length of the memory block
        !          2865:  * @enc:  the charset encoding if known
        !          2866:  *
        !          2867:  * Create a buffered parser input for the progressive parsing for the input
        !          2868:  * from an immutable memory area. This will not copy the memory area to
        !          2869:  * the buffer, but the memory is expected to be available until the end of
        !          2870:  * the parsing, this is useful for example when using mmap'ed file.
        !          2871:  *
        !          2872:  * Returns the new parser input or NULL
        !          2873:  */
        !          2874: xmlParserInputBufferPtr
        !          2875: xmlParserInputBufferCreateStatic(const char *mem, int size,
        !          2876:                                  xmlCharEncoding enc) {
        !          2877:     xmlParserInputBufferPtr ret;
        !          2878: 
        !          2879:     if (size <= 0) return(NULL);
        !          2880:     if (mem == NULL) return(NULL);
        !          2881: 
        !          2882:     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
        !          2883:     if (ret == NULL) {
        !          2884:        xmlIOErrMemory("creating input buffer");
        !          2885:        return(NULL);
        !          2886:     }
        !          2887:     memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
        !          2888:     ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size);
        !          2889:     if (ret->buffer == NULL) {
        !          2890:         xmlFree(ret);
        !          2891:        return(NULL);
        !          2892:     }
        !          2893:     ret->encoder = xmlGetCharEncodingHandler(enc);
        !          2894:     if (ret->encoder != NULL)
        !          2895:         ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
        !          2896:     else
        !          2897:         ret->raw = NULL;
        !          2898:     ret->compressed = -1;
        !          2899:     ret->context = (void *) mem;
        !          2900:     ret->readcallback = NULL;
        !          2901:     ret->closecallback = NULL;
        !          2902: 
        !          2903:     return(ret);
        !          2904: }
        !          2905: 
        !          2906: #ifdef LIBXML_OUTPUT_ENABLED
        !          2907: /**
        !          2908:  * xmlOutputBufferCreateFd:
        !          2909:  * @fd:  a file descriptor number
        !          2910:  * @encoder:  the encoding converter or NULL
        !          2911:  *
        !          2912:  * Create a buffered output for the progressive saving
        !          2913:  * to a file descriptor
        !          2914:  *
        !          2915:  * Returns the new parser output or NULL
        !          2916:  */
        !          2917: xmlOutputBufferPtr
        !          2918: xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
        !          2919:     xmlOutputBufferPtr ret;
        !          2920: 
        !          2921:     if (fd < 0) return(NULL);
        !          2922: 
        !          2923:     ret = xmlAllocOutputBufferInternal(encoder);
        !          2924:     if (ret != NULL) {
        !          2925:         ret->context = (void *) (long) fd;
        !          2926:        ret->writecallback = xmlFdWrite;
        !          2927:        ret->closecallback = NULL;
        !          2928:     }
        !          2929: 
        !          2930:     return(ret);
        !          2931: }
        !          2932: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2933: 
        !          2934: /**
        !          2935:  * xmlParserInputBufferCreateIO:
        !          2936:  * @ioread:  an I/O read function
        !          2937:  * @ioclose:  an I/O close function
        !          2938:  * @ioctx:  an I/O handler
        !          2939:  * @enc:  the charset encoding if known
        !          2940:  *
        !          2941:  * Create a buffered parser input for the progressive parsing for the input
        !          2942:  * from an I/O handler
        !          2943:  *
        !          2944:  * Returns the new parser input or NULL
        !          2945:  */
        !          2946: xmlParserInputBufferPtr
        !          2947: xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
        !          2948:         xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
        !          2949:     xmlParserInputBufferPtr ret;
        !          2950: 
        !          2951:     if (ioread == NULL) return(NULL);
        !          2952: 
        !          2953:     ret = xmlAllocParserInputBuffer(enc);
        !          2954:     if (ret != NULL) {
        !          2955:         ret->context = (void *) ioctx;
        !          2956:        ret->readcallback = ioread;
        !          2957:        ret->closecallback = ioclose;
        !          2958:     }
        !          2959: 
        !          2960:     return(ret);
        !          2961: }
        !          2962: 
        !          2963: #ifdef LIBXML_OUTPUT_ENABLED
        !          2964: /**
        !          2965:  * xmlOutputBufferCreateIO:
        !          2966:  * @iowrite:  an I/O write function
        !          2967:  * @ioclose:  an I/O close function
        !          2968:  * @ioctx:  an I/O handler
        !          2969:  * @encoder:  the charset encoding if known
        !          2970:  *
        !          2971:  * Create a buffered output for the progressive saving
        !          2972:  * to an I/O handler
        !          2973:  *
        !          2974:  * Returns the new parser output or NULL
        !          2975:  */
        !          2976: xmlOutputBufferPtr
        !          2977: xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
        !          2978:         xmlOutputCloseCallback  ioclose, void *ioctx,
        !          2979:         xmlCharEncodingHandlerPtr encoder) {
        !          2980:     xmlOutputBufferPtr ret;
        !          2981: 
        !          2982:     if (iowrite == NULL) return(NULL);
        !          2983: 
        !          2984:     ret = xmlAllocOutputBufferInternal(encoder);
        !          2985:     if (ret != NULL) {
        !          2986:         ret->context = (void *) ioctx;
        !          2987:        ret->writecallback = iowrite;
        !          2988:        ret->closecallback = ioclose;
        !          2989:     }
        !          2990: 
        !          2991:     return(ret);
        !          2992: }
        !          2993: #endif /* LIBXML_OUTPUT_ENABLED */
        !          2994: 
        !          2995: /**
        !          2996:  * xmlParserInputBufferCreateFilenameDefault:
        !          2997:  * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
        !          2998:  *
        !          2999:  * Registers a callback for URI input file handling
        !          3000:  *
        !          3001:  * Returns the old value of the registration function
        !          3002:  */
        !          3003: xmlParserInputBufferCreateFilenameFunc
        !          3004: xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
        !          3005: {
        !          3006:     xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
        !          3007:     if (old == NULL) {
        !          3008:                old = __xmlParserInputBufferCreateFilename;
        !          3009:        }
        !          3010: 
        !          3011:     xmlParserInputBufferCreateFilenameValue = func;
        !          3012:     return(old);
        !          3013: }
        !          3014: 
        !          3015: /**
        !          3016:  * xmlOutputBufferCreateFilenameDefault:
        !          3017:  * @func: function pointer to the new OutputBufferCreateFilenameFunc
        !          3018:  *
        !          3019:  * Registers a callback for URI output file handling
        !          3020:  *
        !          3021:  * Returns the old value of the registration function
        !          3022:  */
        !          3023: xmlOutputBufferCreateFilenameFunc
        !          3024: xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
        !          3025: {
        !          3026:     xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
        !          3027: #ifdef LIBXML_OUTPUT_ENABLED
        !          3028:     if (old == NULL) {
        !          3029:                old = __xmlOutputBufferCreateFilename;
        !          3030:        }
        !          3031: #endif
        !          3032:     xmlOutputBufferCreateFilenameValue = func;
        !          3033:     return(old);
        !          3034: }
        !          3035: 
        !          3036: /**
        !          3037:  * xmlParserInputBufferPush:
        !          3038:  * @in:  a buffered parser input
        !          3039:  * @len:  the size in bytes of the array.
        !          3040:  * @buf:  an char array
        !          3041:  *
        !          3042:  * Push the content of the arry in the input buffer
        !          3043:  * This routine handle the I18N transcoding to internal UTF-8
        !          3044:  * This is used when operating the parser in progressive (push) mode.
        !          3045:  *
        !          3046:  * Returns the number of chars read and stored in the buffer, or -1
        !          3047:  *         in case of error.
        !          3048:  */
        !          3049: int
        !          3050: xmlParserInputBufferPush(xmlParserInputBufferPtr in,
        !          3051:                         int len, const char *buf) {
        !          3052:     int nbchars = 0;
        !          3053:     int ret;
        !          3054: 
        !          3055:     if (len < 0) return(0);
        !          3056:     if ((in == NULL) || (in->error)) return(-1);
        !          3057:     if (in->encoder != NULL) {
        !          3058:         unsigned int use;
        !          3059: 
        !          3060:         /*
        !          3061:         * Store the data in the incoming raw buffer
        !          3062:         */
        !          3063:         if (in->raw == NULL) {
        !          3064:            in->raw = xmlBufferCreate();
        !          3065:        }
        !          3066:        ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
        !          3067:        if (ret != 0)
        !          3068:            return(-1);
        !          3069: 
        !          3070:        /*
        !          3071:         * convert as much as possible to the parser reading buffer.
        !          3072:         */
        !          3073:        use = in->raw->use;
        !          3074:        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
        !          3075:        if (nbchars < 0) {
        !          3076:            xmlIOErr(XML_IO_ENCODER, NULL);
        !          3077:            in->error = XML_IO_ENCODER;
        !          3078:            return(-1);
        !          3079:        }
        !          3080:        in->rawconsumed += (use - in->raw->use);
        !          3081:     } else {
        !          3082:        nbchars = len;
        !          3083:         ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
        !          3084:        if (ret != 0)
        !          3085:            return(-1);
        !          3086:     }
        !          3087: #ifdef DEBUG_INPUT
        !          3088:     xmlGenericError(xmlGenericErrorContext,
        !          3089:            "I/O: pushed %d chars, buffer %d/%d\n",
        !          3090:             nbchars, in->buffer->use, in->buffer->size);
        !          3091: #endif
        !          3092:     return(nbchars);
        !          3093: }
        !          3094: 
        !          3095: /**
        !          3096:  * endOfInput:
        !          3097:  *
        !          3098:  * When reading from an Input channel indicated end of file or error
        !          3099:  * don't reread from it again.
        !          3100:  */
        !          3101: static int
        !          3102: endOfInput (void * context ATTRIBUTE_UNUSED,
        !          3103:            char * buffer ATTRIBUTE_UNUSED,
        !          3104:            int len ATTRIBUTE_UNUSED) {
        !          3105:     return(0);
        !          3106: }
        !          3107: 
        !          3108: /**
        !          3109:  * xmlParserInputBufferGrow:
        !          3110:  * @in:  a buffered parser input
        !          3111:  * @len:  indicative value of the amount of chars to read
        !          3112:  *
        !          3113:  * Grow up the content of the input buffer, the old data are preserved
        !          3114:  * This routine handle the I18N transcoding to internal UTF-8
        !          3115:  * This routine is used when operating the parser in normal (pull) mode
        !          3116:  *
        !          3117:  * TODO: one should be able to remove one extra copy by copying directly
        !          3118:  *       onto in->buffer or in->raw
        !          3119:  *
        !          3120:  * Returns the number of chars read and stored in the buffer, or -1
        !          3121:  *         in case of error.
        !          3122:  */
        !          3123: int
        !          3124: xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
        !          3125:     char *buffer = NULL;
        !          3126:     int res = 0;
        !          3127:     int nbchars = 0;
        !          3128:     int buffree;
        !          3129:     unsigned int needSize;
        !          3130: 
        !          3131:     if ((in == NULL) || (in->error)) return(-1);
        !          3132:     if ((len <= MINLEN) && (len != 4))
        !          3133:         len = MINLEN;
        !          3134: 
        !          3135:     buffree = in->buffer->size - in->buffer->use;
        !          3136:     if (buffree <= 0) {
        !          3137:        xmlIOErr(XML_IO_BUFFER_FULL, NULL);
        !          3138:        in->error = XML_IO_BUFFER_FULL;
        !          3139:        return(-1);
        !          3140:     }
        !          3141: 
        !          3142:     needSize = in->buffer->use + len + 1;
        !          3143:     if (needSize > in->buffer->size){
        !          3144:         if (!xmlBufferResize(in->buffer, needSize)){
        !          3145:            xmlIOErrMemory("growing input buffer");
        !          3146:            in->error = XML_ERR_NO_MEMORY;
        !          3147:             return(-1);
        !          3148:         }
        !          3149:     }
        !          3150:     buffer = (char *)&in->buffer->content[in->buffer->use];
        !          3151: 
        !          3152:     /*
        !          3153:      * Call the read method for this I/O type.
        !          3154:      */
        !          3155:     if (in->readcallback != NULL) {
        !          3156:        res = in->readcallback(in->context, &buffer[0], len);
        !          3157:        if (res <= 0)
        !          3158:            in->readcallback = endOfInput;
        !          3159:     } else {
        !          3160:        xmlIOErr(XML_IO_NO_INPUT, NULL);
        !          3161:        in->error = XML_IO_NO_INPUT;
        !          3162:        return(-1);
        !          3163:     }
        !          3164:     if (res < 0) {
        !          3165:        return(-1);
        !          3166:     }
        !          3167:     len = res;
        !          3168:     if (in->encoder != NULL) {
        !          3169:         unsigned int use;
        !          3170: 
        !          3171:         /*
        !          3172:         * Store the data in the incoming raw buffer
        !          3173:         */
        !          3174:         if (in->raw == NULL) {
        !          3175:            in->raw = xmlBufferCreate();
        !          3176:        }
        !          3177:        res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
        !          3178:        if (res != 0)
        !          3179:            return(-1);
        !          3180: 
        !          3181:        /*
        !          3182:         * convert as much as possible to the parser reading buffer.
        !          3183:         */
        !          3184:        use = in->raw->use;
        !          3185:        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
        !          3186:        if (nbchars < 0) {
        !          3187:            xmlIOErr(XML_IO_ENCODER, NULL);
        !          3188:            in->error = XML_IO_ENCODER;
        !          3189:            return(-1);
        !          3190:        }
        !          3191:        in->rawconsumed += (use - in->raw->use);
        !          3192:     } else {
        !          3193:        nbchars = len;
        !          3194:        in->buffer->use += nbchars;
        !          3195:        buffer[nbchars] = 0;
        !          3196:     }
        !          3197: #ifdef DEBUG_INPUT
        !          3198:     xmlGenericError(xmlGenericErrorContext,
        !          3199:            "I/O: read %d chars, buffer %d/%d\n",
        !          3200:             nbchars, in->buffer->use, in->buffer->size);
        !          3201: #endif
        !          3202:     return(nbchars);
        !          3203: }
        !          3204: 
        !          3205: /**
        !          3206:  * xmlParserInputBufferRead:
        !          3207:  * @in:  a buffered parser input
        !          3208:  * @len:  indicative value of the amount of chars to read
        !          3209:  *
        !          3210:  * Refresh the content of the input buffer, the old data are considered
        !          3211:  * consumed
        !          3212:  * This routine handle the I18N transcoding to internal UTF-8
        !          3213:  *
        !          3214:  * Returns the number of chars read and stored in the buffer, or -1
        !          3215:  *         in case of error.
        !          3216:  */
        !          3217: int
        !          3218: xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
        !          3219:     if ((in == NULL) || (in->error)) return(-1);
        !          3220:     if (in->readcallback != NULL)
        !          3221:        return(xmlParserInputBufferGrow(in, len));
        !          3222:     else if ((in->buffer != NULL) &&
        !          3223:              (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE))
        !          3224:        return(0);
        !          3225:     else
        !          3226:         return(-1);
        !          3227: }
        !          3228: 
        !          3229: #ifdef LIBXML_OUTPUT_ENABLED
        !          3230: /**
        !          3231:  * xmlOutputBufferWrite:
        !          3232:  * @out:  a buffered parser output
        !          3233:  * @len:  the size in bytes of the array.
        !          3234:  * @buf:  an char array
        !          3235:  *
        !          3236:  * Write the content of the array in the output I/O buffer
        !          3237:  * This routine handle the I18N transcoding from internal UTF-8
        !          3238:  * The buffer is lossless, i.e. will store in case of partial
        !          3239:  * or delayed writes.
        !          3240:  *
        !          3241:  * Returns the number of chars immediately written, or -1
        !          3242:  *         in case of error.
        !          3243:  */
        !          3244: int
        !          3245: xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
        !          3246:     int nbchars = 0; /* number of chars to output to I/O */
        !          3247:     int ret;         /* return from function call */
        !          3248:     int written = 0; /* number of char written to I/O so far */
        !          3249:     int chunk;       /* number of byte curreent processed from buf */
        !          3250: 
        !          3251:     if ((out == NULL) || (out->error)) return(-1);
        !          3252:     if (len < 0) return(0);
        !          3253:     if (out->error) return(-1);
        !          3254: 
        !          3255:     do {
        !          3256:        chunk = len;
        !          3257:        if (chunk > 4 * MINLEN)
        !          3258:            chunk = 4 * MINLEN;
        !          3259: 
        !          3260:        /*
        !          3261:         * first handle encoding stuff.
        !          3262:         */
        !          3263:        if (out->encoder != NULL) {
        !          3264:            /*
        !          3265:             * Store the data in the incoming raw buffer
        !          3266:             */
        !          3267:            if (out->conv == NULL) {
        !          3268:                out->conv = xmlBufferCreate();
        !          3269:            }
        !          3270:            ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
        !          3271:            if (ret != 0)
        !          3272:                return(-1);
        !          3273: 
        !          3274:            if ((out->buffer->use < MINLEN) && (chunk == len))
        !          3275:                goto done;
        !          3276: 
        !          3277:            /*
        !          3278:             * convert as much as possible to the parser reading buffer.
        !          3279:             */
        !          3280:            ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
        !          3281:            if ((ret < 0) && (ret != -3)) {
        !          3282:                xmlIOErr(XML_IO_ENCODER, NULL);
        !          3283:                out->error = XML_IO_ENCODER;
        !          3284:                return(-1);
        !          3285:            }
        !          3286:            nbchars = out->conv->use;
        !          3287:        } else {
        !          3288:            ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
        !          3289:            if (ret != 0)
        !          3290:                return(-1);
        !          3291:            nbchars = out->buffer->use;
        !          3292:        }
        !          3293:        buf += chunk;
        !          3294:        len -= chunk;
        !          3295: 
        !          3296:        if ((nbchars < MINLEN) && (len <= 0))
        !          3297:            goto done;
        !          3298: 
        !          3299:        if (out->writecallback) {
        !          3300:            /*
        !          3301:             * second write the stuff to the I/O channel
        !          3302:             */
        !          3303:            if (out->encoder != NULL) {
        !          3304:                ret = out->writecallback(out->context,
        !          3305:                                 (const char *)out->conv->content, nbchars);
        !          3306:                if (ret >= 0)
        !          3307:                    xmlBufferShrink(out->conv, ret);
        !          3308:            } else {
        !          3309:                ret = out->writecallback(out->context,
        !          3310:                                 (const char *)out->buffer->content, nbchars);
        !          3311:                if (ret >= 0)
        !          3312:                    xmlBufferShrink(out->buffer, ret);
        !          3313:            }
        !          3314:            if (ret < 0) {
        !          3315:                xmlIOErr(XML_IO_WRITE, NULL);
        !          3316:                out->error = XML_IO_WRITE;
        !          3317:                return(ret);
        !          3318:            }
        !          3319:            out->written += ret;
        !          3320:        }
        !          3321:        written += nbchars;
        !          3322:     } while (len > 0);
        !          3323: 
        !          3324: done:
        !          3325: #ifdef DEBUG_INPUT
        !          3326:     xmlGenericError(xmlGenericErrorContext,
        !          3327:            "I/O: wrote %d chars\n", written);
        !          3328: #endif
        !          3329:     return(written);
        !          3330: }
        !          3331: 
        !          3332: /**
        !          3333:  * xmlEscapeContent:
        !          3334:  * @out:  a pointer to an array of bytes to store the result
        !          3335:  * @outlen:  the length of @out
        !          3336:  * @in:  a pointer to an array of unescaped UTF-8 bytes
        !          3337:  * @inlen:  the length of @in
        !          3338:  *
        !          3339:  * Take a block of UTF-8 chars in and escape them.
        !          3340:  * Returns 0 if success, or -1 otherwise
        !          3341:  * The value of @inlen after return is the number of octets consumed
        !          3342:  *     if the return value is positive, else unpredictable.
        !          3343:  * The value of @outlen after return is the number of octets consumed.
        !          3344:  */
        !          3345: static int
        !          3346: xmlEscapeContent(unsigned char* out, int *outlen,
        !          3347:                  const xmlChar* in, int *inlen) {
        !          3348:     unsigned char* outstart = out;
        !          3349:     const unsigned char* base = in;
        !          3350:     unsigned char* outend = out + *outlen;
        !          3351:     const unsigned char* inend;
        !          3352: 
        !          3353:     inend = in + (*inlen);
        !          3354: 
        !          3355:     while ((in < inend) && (out < outend)) {
        !          3356:        if (*in == '<') {
        !          3357:            if (outend - out < 4) break;
        !          3358:            *out++ = '&';
        !          3359:            *out++ = 'l';
        !          3360:            *out++ = 't';
        !          3361:            *out++ = ';';
        !          3362:        } else if (*in == '>') {
        !          3363:            if (outend - out < 4) break;
        !          3364:            *out++ = '&';
        !          3365:            *out++ = 'g';
        !          3366:            *out++ = 't';
        !          3367:            *out++ = ';';
        !          3368:        } else if (*in == '&') {
        !          3369:            if (outend - out < 5) break;
        !          3370:            *out++ = '&';
        !          3371:            *out++ = 'a';
        !          3372:            *out++ = 'm';
        !          3373:            *out++ = 'p';
        !          3374:            *out++ = ';';
        !          3375:        } else if (*in == '\r') {
        !          3376:            if (outend - out < 5) break;
        !          3377:            *out++ = '&';
        !          3378:            *out++ = '#';
        !          3379:            *out++ = '1';
        !          3380:            *out++ = '3';
        !          3381:            *out++ = ';';
        !          3382:        } else {
        !          3383:            *out++ = (unsigned char) *in;
        !          3384:        }
        !          3385:        ++in;
        !          3386:     }
        !          3387:     *outlen = out - outstart;
        !          3388:     *inlen = in - base;
        !          3389:     return(0);
        !          3390: }
        !          3391: 
        !          3392: /**
        !          3393:  * xmlOutputBufferWriteEscape:
        !          3394:  * @out:  a buffered parser output
        !          3395:  * @str:  a zero terminated UTF-8 string
        !          3396:  * @escaping:  an optional escaping function (or NULL)
        !          3397:  *
        !          3398:  * Write the content of the string in the output I/O buffer
        !          3399:  * This routine escapes the caracters and then handle the I18N
        !          3400:  * transcoding from internal UTF-8
        !          3401:  * The buffer is lossless, i.e. will store in case of partial
        !          3402:  * or delayed writes.
        !          3403:  *
        !          3404:  * Returns the number of chars immediately written, or -1
        !          3405:  *         in case of error.
        !          3406:  */
        !          3407: int
        !          3408: xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
        !          3409:                            xmlCharEncodingOutputFunc escaping) {
        !          3410:     int nbchars = 0; /* number of chars to output to I/O */
        !          3411:     int ret;         /* return from function call */
        !          3412:     int written = 0; /* number of char written to I/O so far */
        !          3413:     int oldwritten=0;/* loop guard */
        !          3414:     int chunk;       /* number of byte currently processed from str */
        !          3415:     int len;         /* number of bytes in str */
        !          3416:     int cons;        /* byte from str consumed */
        !          3417: 
        !          3418:     if ((out == NULL) || (out->error) || (str == NULL) ||
        !          3419:         (out->buffer == NULL) ||
        !          3420:        (out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1);
        !          3421:     len = strlen((const char *)str);
        !          3422:     if (len < 0) return(0);
        !          3423:     if (out->error) return(-1);
        !          3424:     if (escaping == NULL) escaping = xmlEscapeContent;
        !          3425: 
        !          3426:     do {
        !          3427:         oldwritten = written;
        !          3428: 
        !          3429:         /*
        !          3430:         * how many bytes to consume and how many bytes to store.
        !          3431:         */
        !          3432:        cons = len;
        !          3433:        chunk = (out->buffer->size - out->buffer->use) - 1;
        !          3434: 
        !          3435:         /*
        !          3436:         * make sure we have enough room to save first, if this is
        !          3437:         * not the case force a flush, but make sure we stay in the loop
        !          3438:         */
        !          3439:        if (chunk < 40) {
        !          3440:            if (xmlBufferGrow(out->buffer, out->buffer->size + 100) < 0)
        !          3441:                return(-1);
        !          3442:             oldwritten = -1;
        !          3443:            continue;
        !          3444:        }
        !          3445: 
        !          3446:        /*
        !          3447:         * first handle encoding stuff.
        !          3448:         */
        !          3449:        if (out->encoder != NULL) {
        !          3450:            /*
        !          3451:             * Store the data in the incoming raw buffer
        !          3452:             */
        !          3453:            if (out->conv == NULL) {
        !          3454:                out->conv = xmlBufferCreate();
        !          3455:            }
        !          3456:            ret = escaping(out->buffer->content + out->buffer->use ,
        !          3457:                           &chunk, str, &cons);
        !          3458:            if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
        !          3459:                return(-1);
        !          3460:            out->buffer->use += chunk;
        !          3461:            out->buffer->content[out->buffer->use] = 0;
        !          3462: 
        !          3463:            if ((out->buffer->use < MINLEN) && (cons == len))
        !          3464:                goto done;
        !          3465: 
        !          3466:            /*
        !          3467:             * convert as much as possible to the output buffer.
        !          3468:             */
        !          3469:            ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
        !          3470:            if ((ret < 0) && (ret != -3)) {
        !          3471:                xmlIOErr(XML_IO_ENCODER, NULL);
        !          3472:                out->error = XML_IO_ENCODER;
        !          3473:                return(-1);
        !          3474:            }
        !          3475:            nbchars = out->conv->use;
        !          3476:        } else {
        !          3477:            ret = escaping(out->buffer->content + out->buffer->use ,
        !          3478:                           &chunk, str, &cons);
        !          3479:            if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
        !          3480:                return(-1);
        !          3481:            out->buffer->use += chunk;
        !          3482:            out->buffer->content[out->buffer->use] = 0;
        !          3483:            nbchars = out->buffer->use;
        !          3484:        }
        !          3485:        str += cons;
        !          3486:        len -= cons;
        !          3487: 
        !          3488:        if ((nbchars < MINLEN) && (len <= 0))
        !          3489:            goto done;
        !          3490: 
        !          3491:        if (out->writecallback) {
        !          3492:            /*
        !          3493:             * second write the stuff to the I/O channel
        !          3494:             */
        !          3495:            if (out->encoder != NULL) {
        !          3496:                ret = out->writecallback(out->context,
        !          3497:                                 (const char *)out->conv->content, nbchars);
        !          3498:                if (ret >= 0)
        !          3499:                    xmlBufferShrink(out->conv, ret);
        !          3500:            } else {
        !          3501:                ret = out->writecallback(out->context,
        !          3502:                                 (const char *)out->buffer->content, nbchars);
        !          3503:                if (ret >= 0)
        !          3504:                    xmlBufferShrink(out->buffer, ret);
        !          3505:            }
        !          3506:            if (ret < 0) {
        !          3507:                xmlIOErr(XML_IO_WRITE, NULL);
        !          3508:                out->error = XML_IO_WRITE;
        !          3509:                return(ret);
        !          3510:            }
        !          3511:            out->written += ret;
        !          3512:        } else if (out->buffer->size - out->buffer->use < MINLEN) {
        !          3513:            xmlBufferResize(out->buffer, out->buffer->size + MINLEN);
        !          3514:        }
        !          3515:        written += nbchars;
        !          3516:     } while ((len > 0) && (oldwritten != written));
        !          3517: 
        !          3518: done:
        !          3519: #ifdef DEBUG_INPUT
        !          3520:     xmlGenericError(xmlGenericErrorContext,
        !          3521:            "I/O: wrote %d chars\n", written);
        !          3522: #endif
        !          3523:     return(written);
        !          3524: }
        !          3525: 
        !          3526: /**
        !          3527:  * xmlOutputBufferWriteString:
        !          3528:  * @out:  a buffered parser output
        !          3529:  * @str:  a zero terminated C string
        !          3530:  *
        !          3531:  * Write the content of the string in the output I/O buffer
        !          3532:  * This routine handle the I18N transcoding from internal UTF-8
        !          3533:  * The buffer is lossless, i.e. will store in case of partial
        !          3534:  * or delayed writes.
        !          3535:  *
        !          3536:  * Returns the number of chars immediately written, or -1
        !          3537:  *         in case of error.
        !          3538:  */
        !          3539: int
        !          3540: xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
        !          3541:     int len;
        !          3542: 
        !          3543:     if ((out == NULL) || (out->error)) return(-1);
        !          3544:     if (str == NULL)
        !          3545:         return(-1);
        !          3546:     len = strlen(str);
        !          3547: 
        !          3548:     if (len > 0)
        !          3549:        return(xmlOutputBufferWrite(out, len, str));
        !          3550:     return(len);
        !          3551: }
        !          3552: 
        !          3553: /**
        !          3554:  * xmlOutputBufferFlush:
        !          3555:  * @out:  a buffered output
        !          3556:  *
        !          3557:  * flushes the output I/O channel
        !          3558:  *
        !          3559:  * Returns the number of byte written or -1 in case of error.
        !          3560:  */
        !          3561: int
        !          3562: xmlOutputBufferFlush(xmlOutputBufferPtr out) {
        !          3563:     int nbchars = 0, ret = 0;
        !          3564: 
        !          3565:     if ((out == NULL) || (out->error)) return(-1);
        !          3566:     /*
        !          3567:      * first handle encoding stuff.
        !          3568:      */
        !          3569:     if ((out->conv != NULL) && (out->encoder != NULL)) {
        !          3570:        /*
        !          3571:         * convert as much as possible to the parser reading buffer.
        !          3572:         */
        !          3573:        nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
        !          3574:        if (nbchars < 0) {
        !          3575:            xmlIOErr(XML_IO_ENCODER, NULL);
        !          3576:            out->error = XML_IO_ENCODER;
        !          3577:            return(-1);
        !          3578:        }
        !          3579:     }
        !          3580: 
        !          3581:     /*
        !          3582:      * second flush the stuff to the I/O channel
        !          3583:      */
        !          3584:     if ((out->conv != NULL) && (out->encoder != NULL) &&
        !          3585:        (out->writecallback != NULL)) {
        !          3586:        ret = out->writecallback(out->context,
        !          3587:                   (const char *)out->conv->content, out->conv->use);
        !          3588:        if (ret >= 0)
        !          3589:            xmlBufferShrink(out->conv, ret);
        !          3590:     } else if (out->writecallback != NULL) {
        !          3591:        ret = out->writecallback(out->context,
        !          3592:                   (const char *)out->buffer->content, out->buffer->use);
        !          3593:        if (ret >= 0)
        !          3594:            xmlBufferShrink(out->buffer, ret);
        !          3595:     }
        !          3596:     if (ret < 0) {
        !          3597:        xmlIOErr(XML_IO_FLUSH, NULL);
        !          3598:        out->error = XML_IO_FLUSH;
        !          3599:        return(ret);
        !          3600:     }
        !          3601:     out->written += ret;
        !          3602: 
        !          3603: #ifdef DEBUG_INPUT
        !          3604:     xmlGenericError(xmlGenericErrorContext,
        !          3605:            "I/O: flushed %d chars\n", ret);
        !          3606: #endif
        !          3607:     return(ret);
        !          3608: }
        !          3609: #endif /* LIBXML_OUTPUT_ENABLED */
        !          3610: 
        !          3611: /**
        !          3612:  * xmlParserGetDirectory:
        !          3613:  * @filename:  the path to a file
        !          3614:  *
        !          3615:  * lookup the directory for that file
        !          3616:  *
        !          3617:  * Returns a new allocated string containing the directory, or NULL.
        !          3618:  */
        !          3619: char *
        !          3620: xmlParserGetDirectory(const char *filename) {
        !          3621:     char *ret = NULL;
        !          3622:     char dir[1024];
        !          3623:     char *cur;
        !          3624: 
        !          3625: #ifdef _WIN32_WCE  /* easy way by now ... wince does not have dirs! */
        !          3626:     return NULL;
        !          3627: #endif
        !          3628: 
        !          3629:     if (xmlInputCallbackInitialized == 0)
        !          3630:        xmlRegisterDefaultInputCallbacks();
        !          3631: 
        !          3632:     if (filename == NULL) return(NULL);
        !          3633: 
        !          3634: #if defined(WIN32) && !defined(__CYGWIN__)
        !          3635: #   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
        !          3636: #else
        !          3637: #   define IS_XMLPGD_SEP(ch) (ch=='/')
        !          3638: #endif
        !          3639: 
        !          3640:     strncpy(dir, filename, 1023);
        !          3641:     dir[1023] = 0;
        !          3642:     cur = &dir[strlen(dir)];
        !          3643:     while (cur > dir) {
        !          3644:          if (IS_XMLPGD_SEP(*cur)) break;
        !          3645:         cur --;
        !          3646:     }
        !          3647:     if (IS_XMLPGD_SEP(*cur)) {
        !          3648:         if (cur == dir) dir[1] = 0;
        !          3649:        else *cur = 0;
        !          3650:        ret = xmlMemStrdup(dir);
        !          3651:     } else {
        !          3652:         if (getcwd(dir, 1024) != NULL) {
        !          3653:            dir[1023] = 0;
        !          3654:            ret = xmlMemStrdup(dir);
        !          3655:        }
        !          3656:     }
        !          3657:     return(ret);
        !          3658: #undef IS_XMLPGD_SEP
        !          3659: }
        !          3660: 
        !          3661: /****************************************************************
        !          3662:  *                                                             *
        !          3663:  *             External entities loading                       *
        !          3664:  *                                                             *
        !          3665:  ****************************************************************/
        !          3666: 
        !          3667: /**
        !          3668:  * xmlCheckHTTPInput:
        !          3669:  * @ctxt: an XML parser context
        !          3670:  * @ret: an XML parser input
        !          3671:  *
        !          3672:  * Check an input in case it was created from an HTTP stream, in that
        !          3673:  * case it will handle encoding and update of the base URL in case of
        !          3674:  * redirection. It also checks for HTTP errors in which case the input
        !          3675:  * is cleanly freed up and an appropriate error is raised in context
        !          3676:  *
        !          3677:  * Returns the input or NULL in case of HTTP error.
        !          3678:  */
        !          3679: xmlParserInputPtr
        !          3680: xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
        !          3681: #ifdef LIBXML_HTTP_ENABLED
        !          3682:     if ((ret != NULL) && (ret->buf != NULL) &&
        !          3683:         (ret->buf->readcallback == xmlIOHTTPRead) &&
        !          3684:         (ret->buf->context != NULL)) {
        !          3685:         const char *encoding;
        !          3686:         const char *redir;
        !          3687:         const char *mime;
        !          3688:         int code;
        !          3689: 
        !          3690:         code = xmlNanoHTTPReturnCode(ret->buf->context);
        !          3691:         if (code >= 400) {
        !          3692:             /* fatal error */
        !          3693:            if (ret->filename != NULL)
        !          3694:                __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
        !          3695:                          (const char *) ret->filename);
        !          3696:            else
        !          3697:                __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
        !          3698:             xmlFreeInputStream(ret);
        !          3699:             ret = NULL;
        !          3700:         } else {
        !          3701: 
        !          3702:             mime = xmlNanoHTTPMimeType(ret->buf->context);
        !          3703:             if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
        !          3704:                 (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
        !          3705:                 encoding = xmlNanoHTTPEncoding(ret->buf->context);
        !          3706:                 if (encoding != NULL) {
        !          3707:                     xmlCharEncodingHandlerPtr handler;
        !          3708: 
        !          3709:                     handler = xmlFindCharEncodingHandler(encoding);
        !          3710:                     if (handler != NULL) {
        !          3711:                         xmlSwitchInputEncoding(ctxt, ret, handler);
        !          3712:                     } else {
        !          3713:                         __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
        !          3714:                                          "Unknown encoding %s",
        !          3715:                                          BAD_CAST encoding, NULL);
        !          3716:                     }
        !          3717:                     if (ret->encoding == NULL)
        !          3718:                         ret->encoding = xmlStrdup(BAD_CAST encoding);
        !          3719:                 }
        !          3720: #if 0
        !          3721:             } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
        !          3722: #endif
        !          3723:             }
        !          3724:             redir = xmlNanoHTTPRedir(ret->buf->context);
        !          3725:             if (redir != NULL) {
        !          3726:                 if (ret->filename != NULL)
        !          3727:                     xmlFree((xmlChar *) ret->filename);
        !          3728:                 if (ret->directory != NULL) {
        !          3729:                     xmlFree((xmlChar *) ret->directory);
        !          3730:                     ret->directory = NULL;
        !          3731:                 }
        !          3732:                 ret->filename =
        !          3733:                     (char *) xmlStrdup((const xmlChar *) redir);
        !          3734:             }
        !          3735:         }
        !          3736:     }
        !          3737: #endif
        !          3738:     return(ret);
        !          3739: }
        !          3740: 
        !          3741: static int xmlNoNetExists(const char *URL) {
        !          3742:     const char *path;
        !          3743: 
        !          3744:     if (URL == NULL)
        !          3745:        return(0);
        !          3746: 
        !          3747:     if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
        !          3748: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !          3749:        path = &URL[17];
        !          3750: #else
        !          3751:        path = &URL[16];
        !          3752: #endif
        !          3753:     else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
        !          3754: #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
        !          3755:        path = &URL[8];
        !          3756: #else
        !          3757:        path = &URL[7];
        !          3758: #endif
        !          3759:     } else
        !          3760:        path = URL;
        !          3761: 
        !          3762:     return xmlCheckFilename(path);
        !          3763: }
        !          3764: 
        !          3765: #ifdef LIBXML_CATALOG_ENABLED
        !          3766: 
        !          3767: /**
        !          3768:  * xmlResolveResourceFromCatalog:
        !          3769:  * @URL:  the URL for the entity to load
        !          3770:  * @ID:  the System ID for the entity to load
        !          3771:  * @ctxt:  the context in which the entity is called or NULL
        !          3772:  *
        !          3773:  * Resolves the URL and ID against the appropriate catalog.
        !          3774:  * This function is used by xmlDefaultExternalEntityLoader and
        !          3775:  * xmlNoNetExternalEntityLoader.
        !          3776:  *
        !          3777:  * Returns a new allocated URL, or NULL.
        !          3778:  */
        !          3779: static xmlChar *
        !          3780: xmlResolveResourceFromCatalog(const char *URL, const char *ID,
        !          3781:                               xmlParserCtxtPtr ctxt) {
        !          3782:     xmlChar *resource = NULL;
        !          3783:     xmlCatalogAllow pref;
        !          3784: 
        !          3785:     /*
        !          3786:      * If the resource doesn't exists as a file,
        !          3787:      * try to load it from the resource pointed in the catalogs
        !          3788:      */
        !          3789:     pref = xmlCatalogGetDefaults();
        !          3790: 
        !          3791:     if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
        !          3792:        /*
        !          3793:         * Do a local lookup
        !          3794:         */
        !          3795:        if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
        !          3796:            ((pref == XML_CATA_ALLOW_ALL) ||
        !          3797:             (pref == XML_CATA_ALLOW_DOCUMENT))) {
        !          3798:            resource = xmlCatalogLocalResolve(ctxt->catalogs,
        !          3799:                                              (const xmlChar *)ID,
        !          3800:                                              (const xmlChar *)URL);
        !          3801:         }
        !          3802:        /*
        !          3803:         * Try a global lookup
        !          3804:         */
        !          3805:        if ((resource == NULL) &&
        !          3806:            ((pref == XML_CATA_ALLOW_ALL) ||
        !          3807:             (pref == XML_CATA_ALLOW_GLOBAL))) {
        !          3808:            resource = xmlCatalogResolve((const xmlChar *)ID,
        !          3809:                                         (const xmlChar *)URL);
        !          3810:        }
        !          3811:        if ((resource == NULL) && (URL != NULL))
        !          3812:            resource = xmlStrdup((const xmlChar *) URL);
        !          3813: 
        !          3814:        /*
        !          3815:         * TODO: do an URI lookup on the reference
        !          3816:         */
        !          3817:        if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
        !          3818:            xmlChar *tmp = NULL;
        !          3819: 
        !          3820:            if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
        !          3821:                ((pref == XML_CATA_ALLOW_ALL) ||
        !          3822:                 (pref == XML_CATA_ALLOW_DOCUMENT))) {
        !          3823:                tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
        !          3824:            }
        !          3825:            if ((tmp == NULL) &&
        !          3826:                ((pref == XML_CATA_ALLOW_ALL) ||
        !          3827:                 (pref == XML_CATA_ALLOW_GLOBAL))) {
        !          3828:                tmp = xmlCatalogResolveURI(resource);
        !          3829:            }
        !          3830: 
        !          3831:            if (tmp != NULL) {
        !          3832:                xmlFree(resource);
        !          3833:                resource = tmp;
        !          3834:            }
        !          3835:        }
        !          3836:     }
        !          3837: 
        !          3838:     return resource;
        !          3839: }
        !          3840: 
        !          3841: #endif
        !          3842: 
        !          3843: /**
        !          3844:  * xmlDefaultExternalEntityLoader:
        !          3845:  * @URL:  the URL for the entity to load
        !          3846:  * @ID:  the System ID for the entity to load
        !          3847:  * @ctxt:  the context in which the entity is called or NULL
        !          3848:  *
        !          3849:  * By default we don't load external entitites, yet.
        !          3850:  *
        !          3851:  * Returns a new allocated xmlParserInputPtr, or NULL.
        !          3852:  */
        !          3853: static xmlParserInputPtr
        !          3854: xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
        !          3855:                                xmlParserCtxtPtr ctxt)
        !          3856: {
        !          3857:     xmlParserInputPtr ret = NULL;
        !          3858:     xmlChar *resource = NULL;
        !          3859: 
        !          3860: #ifdef DEBUG_EXTERNAL_ENTITIES
        !          3861:     xmlGenericError(xmlGenericErrorContext,
        !          3862:                     "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
        !          3863: #endif
        !          3864:     if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
        !          3865:         int options = ctxt->options;
        !          3866: 
        !          3867:        ctxt->options -= XML_PARSE_NONET;
        !          3868:         ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
        !          3869:        ctxt->options = options;
        !          3870:        return(ret);
        !          3871:     }
        !          3872: #ifdef LIBXML_CATALOG_ENABLED
        !          3873:     resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
        !          3874: #endif
        !          3875: 
        !          3876:     if (resource == NULL)
        !          3877:         resource = (xmlChar *) URL;
        !          3878: 
        !          3879:     if (resource == NULL) {
        !          3880:         if (ID == NULL)
        !          3881:             ID = "NULL";
        !          3882:         __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
        !          3883:         return (NULL);
        !          3884:     }
        !          3885:     ret = xmlNewInputFromFile(ctxt, (const char *) resource);
        !          3886:     if ((resource != NULL) && (resource != (xmlChar *) URL))
        !          3887:         xmlFree(resource);
        !          3888:     return (ret);
        !          3889: }
        !          3890: 
        !          3891: static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
        !          3892:        xmlDefaultExternalEntityLoader;
        !          3893: 
        !          3894: /**
        !          3895:  * xmlSetExternalEntityLoader:
        !          3896:  * @f:  the new entity resolver function
        !          3897:  *
        !          3898:  * Changes the defaultexternal entity resolver function for the application
        !          3899:  */
        !          3900: void
        !          3901: xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
        !          3902:     xmlCurrentExternalEntityLoader = f;
        !          3903: }
        !          3904: 
        !          3905: /**
        !          3906:  * xmlGetExternalEntityLoader:
        !          3907:  *
        !          3908:  * Get the default external entity resolver function for the application
        !          3909:  *
        !          3910:  * Returns the xmlExternalEntityLoader function pointer
        !          3911:  */
        !          3912: xmlExternalEntityLoader
        !          3913: xmlGetExternalEntityLoader(void) {
        !          3914:     return(xmlCurrentExternalEntityLoader);
        !          3915: }
        !          3916: 
        !          3917: /**
        !          3918:  * xmlLoadExternalEntity:
        !          3919:  * @URL:  the URL for the entity to load
        !          3920:  * @ID:  the Public ID for the entity to load
        !          3921:  * @ctxt:  the context in which the entity is called or NULL
        !          3922:  *
        !          3923:  * Load an external entity, note that the use of this function for
        !          3924:  * unparsed entities may generate problems
        !          3925:  *
        !          3926:  * Returns the xmlParserInputPtr or NULL
        !          3927:  */
        !          3928: xmlParserInputPtr
        !          3929: xmlLoadExternalEntity(const char *URL, const char *ID,
        !          3930:                       xmlParserCtxtPtr ctxt) {
        !          3931:     if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
        !          3932:        char *canonicFilename;
        !          3933:        xmlParserInputPtr ret;
        !          3934: 
        !          3935:        canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
        !          3936:        if (canonicFilename == NULL) {
        !          3937:             xmlIOErrMemory("building canonical path\n");
        !          3938:            return(NULL);
        !          3939:        }
        !          3940: 
        !          3941:        ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
        !          3942:        xmlFree(canonicFilename);
        !          3943:        return(ret);
        !          3944:     }
        !          3945:     return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
        !          3946: }
        !          3947: 
        !          3948: /************************************************************************
        !          3949:  *                                                                     *
        !          3950:  *             Disabling Network access                                *
        !          3951:  *                                                                     *
        !          3952:  ************************************************************************/
        !          3953: 
        !          3954: /**
        !          3955:  * xmlNoNetExternalEntityLoader:
        !          3956:  * @URL:  the URL for the entity to load
        !          3957:  * @ID:  the System ID for the entity to load
        !          3958:  * @ctxt:  the context in which the entity is called or NULL
        !          3959:  *
        !          3960:  * A specific entity loader disabling network accesses, though still
        !          3961:  * allowing local catalog accesses for resolution.
        !          3962:  *
        !          3963:  * Returns a new allocated xmlParserInputPtr, or NULL.
        !          3964:  */
        !          3965: xmlParserInputPtr
        !          3966: xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
        !          3967:                              xmlParserCtxtPtr ctxt) {
        !          3968:     xmlParserInputPtr input = NULL;
        !          3969:     xmlChar *resource = NULL;
        !          3970: 
        !          3971: #ifdef LIBXML_CATALOG_ENABLED
        !          3972:     resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
        !          3973: #endif
        !          3974: 
        !          3975:     if (resource == NULL)
        !          3976:        resource = (xmlChar *) URL;
        !          3977: 
        !          3978:     if (resource != NULL) {
        !          3979:         if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
        !          3980:             (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
        !          3981:             xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
        !          3982:            if (resource != (xmlChar *) URL)
        !          3983:                xmlFree(resource);
        !          3984:            return(NULL);
        !          3985:        }
        !          3986:     }
        !          3987:     input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
        !          3988:     if (resource != (xmlChar *) URL)
        !          3989:        xmlFree(resource);
        !          3990:     return(input);
        !          3991: }
        !          3992: 
        !          3993: #define bottom_xmlIO
        !          3994: #include "elfgcchack.h"

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>