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

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

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