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

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

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