ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xmlIO.c
Go to the documentation of this file.
00001 /*
00002  * xmlIO.c : implementation of the I/O interfaces used by the parser
00003  *
00004  * See Copyright for the status of this software.
00005  *
00006  * daniel@veillard.com
00007  *
00008  * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char
00009  */
00010 
00011 #define IN_LIBXML
00012 #include "libxml.h"
00013 
00014 #include <string.h>
00015 #ifdef HAVE_ERRNO_H
00016 #include <errno.h>
00017 #endif
00018 
00019 
00020 #ifdef HAVE_SYS_TYPES_H
00021 #include <sys/types.h>
00022 #endif
00023 #ifdef HAVE_SYS_STAT_H
00024 #include <sys/stat.h>
00025 #endif
00026 #ifdef HAVE_FCNTL_H
00027 #include <fcntl.h>
00028 #endif
00029 #ifdef HAVE_UNISTD_H
00030 #include <unistd.h>
00031 #endif
00032 #ifdef HAVE_STDLIB_H
00033 #include <stdlib.h>
00034 #endif
00035 #ifdef HAVE_ZLIB_H
00036 #include <zlib.h>
00037 #endif
00038 
00039 #if defined(WIN32) || defined(_WIN32)
00040 #include <windows.h>
00041 #endif
00042 
00043 #if defined(_WIN32_WCE)
00044 #include <winnls.h> /* for CP_UTF8 */
00045 #endif
00046 
00047 /* Figure a portable way to know if a file is a directory. */
00048 #ifndef HAVE_STAT
00049 #  ifdef HAVE__STAT
00050      /* MS C library seems to define stat and _stat. The definition
00051         is identical. Still, mapping them to each other causes a warning. */
00052 #    ifndef _MSC_VER
00053 #      define stat(x,y) _stat(x,y)
00054 #    endif
00055 #    define HAVE_STAT
00056 #  endif
00057 #else
00058 #  ifdef HAVE__STAT
00059 #    if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
00060 #      define stat _stat
00061 #    endif
00062 #  endif
00063 #endif
00064 #ifdef HAVE_STAT
00065 #  ifndef S_ISDIR
00066 #    ifdef _S_ISDIR
00067 #      define S_ISDIR(x) _S_ISDIR(x)
00068 #    else
00069 #      ifdef S_IFDIR
00070 #        ifndef S_IFMT
00071 #          ifdef _S_IFMT
00072 #            define S_IFMT _S_IFMT
00073 #          endif
00074 #        endif
00075 #        ifdef S_IFMT
00076 #          define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
00077 #        endif
00078 #      endif
00079 #    endif
00080 #  endif
00081 #endif
00082 
00083 #include <libxml/xmlmemory.h>
00084 #include <libxml/parser.h>
00085 #include <libxml/parserInternals.h>
00086 #include <libxml/xmlIO.h>
00087 #include <libxml/uri.h>
00088 #include <libxml/nanohttp.h>
00089 #include <libxml/nanoftp.h>
00090 #include <libxml/xmlerror.h>
00091 #ifdef LIBXML_CATALOG_ENABLED
00092 #include <libxml/catalog.h>
00093 #endif
00094 #include <libxml/globals.h>
00095 
00096 /* #define VERBOSE_FAILURE */
00097 /* #define DEBUG_EXTERNAL_ENTITIES */
00098 /* #define DEBUG_INPUT */
00099 
00100 #ifdef DEBUG_INPUT
00101 #define MINLEN 40
00102 #else
00103 #define MINLEN 4000
00104 #endif
00105 
00106 /*
00107  * Input I/O callback sets
00108  */
00109 typedef struct _xmlInputCallback {
00110     xmlInputMatchCallback matchcallback;
00111     xmlInputOpenCallback opencallback;
00112     xmlInputReadCallback readcallback;
00113     xmlInputCloseCallback closecallback;
00114 } xmlInputCallback;
00115 
00116 #define MAX_INPUT_CALLBACK 15
00117 
00118 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
00119 static int xmlInputCallbackNr = 0;
00120 static int xmlInputCallbackInitialized = 0;
00121 
00122 #ifdef LIBXML_OUTPUT_ENABLED
00123 /*
00124  * Output I/O callback sets
00125  */
00126 typedef struct _xmlOutputCallback {
00127     xmlOutputMatchCallback matchcallback;
00128     xmlOutputOpenCallback opencallback;
00129     xmlOutputWriteCallback writecallback;
00130     xmlOutputCloseCallback closecallback;
00131 } xmlOutputCallback;
00132 
00133 #define MAX_OUTPUT_CALLBACK 15
00134 
00135 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
00136 static int xmlOutputCallbackNr = 0;
00137 static int xmlOutputCallbackInitialized = 0;
00138 
00139 xmlOutputBufferPtr
00140 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
00141 #endif /* LIBXML_OUTPUT_ENABLED */
00142 
00143 /************************************************************************
00144  *                                  *
00145  *      Tree memory error handler               *
00146  *                                  *
00147  ************************************************************************/
00148 
00149 static const char *IOerr[] = {
00150     "Unknown IO error",         /* UNKNOWN */
00151     "Permission denied",    /* EACCES */
00152     "Resource temporarily unavailable",/* EAGAIN */
00153     "Bad file descriptor",  /* EBADF */
00154     "Bad message",      /* EBADMSG */
00155     "Resource busy",        /* EBUSY */
00156     "Operation canceled",   /* ECANCELED */
00157     "No child processes",   /* ECHILD */
00158     "Resource deadlock avoided",/* EDEADLK */
00159     "Domain error",     /* EDOM */
00160     "File exists",      /* EEXIST */
00161     "Bad address",      /* EFAULT */
00162     "File too large",       /* EFBIG */
00163     "Operation in progress",    /* EINPROGRESS */
00164     "Interrupted function call",/* EINTR */
00165     "Invalid argument",     /* EINVAL */
00166     "Input/output error",   /* EIO */
00167     "Is a directory",       /* EISDIR */
00168     "Too many open files",  /* EMFILE */
00169     "Too many links",       /* EMLINK */
00170     "Inappropriate message buffer length",/* EMSGSIZE */
00171     "Filename too long",    /* ENAMETOOLONG */
00172     "Too many open files in system",/* ENFILE */
00173     "No such device",       /* ENODEV */
00174     "No such file or directory",/* ENOENT */
00175     "Exec format error",    /* ENOEXEC */
00176     "No locks available",   /* ENOLCK */
00177     "Not enough space",     /* ENOMEM */
00178     "No space left on device",  /* ENOSPC */
00179     "Function not implemented", /* ENOSYS */
00180     "Not a directory",      /* ENOTDIR */
00181     "Directory not empty",  /* ENOTEMPTY */
00182     "Not supported",        /* ENOTSUP */
00183     "Inappropriate I/O control operation",/* ENOTTY */
00184     "No such device or address",/* ENXIO */
00185     "Operation not permitted",  /* EPERM */
00186     "Broken pipe",      /* EPIPE */
00187     "Result too large",     /* ERANGE */
00188     "Read-only file system",    /* EROFS */
00189     "Invalid seek",     /* ESPIPE */
00190     "No such process",      /* ESRCH */
00191     "Operation timed out",  /* ETIMEDOUT */
00192     "Improper link",        /* EXDEV */
00193     "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */
00194     "encoder error",        /* XML_IO_ENCODER */
00195     "flush error",
00196     "write error",
00197     "no input",
00198     "buffer full",
00199     "loading error",
00200     "not a socket",     /* ENOTSOCK */
00201     "already connected",    /* EISCONN */
00202     "connection refused",   /* ECONNREFUSED */
00203     "unreachable network",  /* ENETUNREACH */
00204     "adddress in use",      /* EADDRINUSE */
00205     "already in use",       /* EALREADY */
00206     "unknown address familly",  /* EAFNOSUPPORT */
00207 };
00208 
00209 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
00210 
00216 static wchar_t *
00217 __xmlIOWin32UTF8ToWChar(const char *u8String)
00218 {
00219     wchar_t *wString = NULL;
00220 
00221     if (u8String) {
00222         int wLen =
00223             MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
00224                                 -1, NULL, 0);
00225         if (wLen) {
00226             wString = xmlMalloc(wLen * sizeof(wchar_t));
00227             if (wString) {
00228                 if (MultiByteToWideChar
00229                     (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
00230                     xmlFree(wString);
00231                     wString = NULL;
00232                 }
00233             }
00234         }
00235     }
00236 
00237     return wString;
00238 }
00239 #endif
00240 
00247 static void
00248 xmlIOErrMemory(const char *extra)
00249 {
00250     __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra);
00251 }
00252 
00261 void
00262 __xmlIOErr(int domain, int code, const char *extra)
00263 {
00264     unsigned int idx;
00265 
00266     if (code == 0) {
00267 #ifdef HAVE_ERRNO_H
00268     if (errno == 0) code = 0;
00269 #ifdef EACCES
00270         else if (errno == EACCES) code = XML_IO_EACCES;
00271 #endif
00272 #ifdef EAGAIN
00273         else if (errno == EAGAIN) code = XML_IO_EAGAIN;
00274 #endif
00275 #ifdef EBADF
00276         else if (errno == EBADF) code = XML_IO_EBADF;
00277 #endif
00278 #ifdef EBADMSG
00279         else if (errno == EBADMSG) code = XML_IO_EBADMSG;
00280 #endif
00281 #ifdef EBUSY
00282         else if (errno == EBUSY) code = XML_IO_EBUSY;
00283 #endif
00284 #ifdef ECANCELED
00285         else if (errno == ECANCELED) code = XML_IO_ECANCELED;
00286 #endif
00287 #ifdef ECHILD
00288         else if (errno == ECHILD) code = XML_IO_ECHILD;
00289 #endif
00290 #ifdef EDEADLK
00291         else if (errno == EDEADLK) code = XML_IO_EDEADLK;
00292 #endif
00293 #ifdef EDOM
00294         else if (errno == EDOM) code = XML_IO_EDOM;
00295 #endif
00296 #ifdef EEXIST
00297         else if (errno == EEXIST) code = XML_IO_EEXIST;
00298 #endif
00299 #ifdef EFAULT
00300         else if (errno == EFAULT) code = XML_IO_EFAULT;
00301 #endif
00302 #ifdef EFBIG
00303         else if (errno == EFBIG) code = XML_IO_EFBIG;
00304 #endif
00305 #ifdef EINPROGRESS
00306         else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
00307 #endif
00308 #ifdef EINTR
00309         else if (errno == EINTR) code = XML_IO_EINTR;
00310 #endif
00311 #ifdef EINVAL
00312         else if (errno == EINVAL) code = XML_IO_EINVAL;
00313 #endif
00314 #ifdef EIO
00315         else if (errno == EIO) code = XML_IO_EIO;
00316 #endif
00317 #ifdef EISDIR
00318         else if (errno == EISDIR) code = XML_IO_EISDIR;
00319 #endif
00320 #ifdef EMFILE
00321         else if (errno == EMFILE) code = XML_IO_EMFILE;
00322 #endif
00323 #ifdef EMLINK
00324         else if (errno == EMLINK) code = XML_IO_EMLINK;
00325 #endif
00326 #ifdef EMSGSIZE
00327         else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE;
00328 #endif
00329 #ifdef ENAMETOOLONG
00330         else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
00331 #endif
00332 #ifdef ENFILE
00333         else if (errno == ENFILE) code = XML_IO_ENFILE;
00334 #endif
00335 #ifdef ENODEV
00336         else if (errno == ENODEV) code = XML_IO_ENODEV;
00337 #endif
00338 #ifdef ENOENT
00339         else if (errno == ENOENT) code = XML_IO_ENOENT;
00340 #endif
00341 #ifdef ENOEXEC
00342         else if (errno == ENOEXEC) code = XML_IO_ENOEXEC;
00343 #endif
00344 #ifdef ENOLCK
00345         else if (errno == ENOLCK) code = XML_IO_ENOLCK;
00346 #endif
00347 #ifdef ENOMEM
00348         else if (errno == ENOMEM) code = XML_IO_ENOMEM;
00349 #endif
00350 #ifdef ENOSPC
00351         else if (errno == ENOSPC) code = XML_IO_ENOSPC;
00352 #endif
00353 #ifdef ENOSYS
00354         else if (errno == ENOSYS) code = XML_IO_ENOSYS;
00355 #endif
00356 #ifdef ENOTDIR
00357         else if (errno == ENOTDIR) code = XML_IO_ENOTDIR;
00358 #endif
00359 #ifdef ENOTEMPTY
00360         else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
00361 #endif
00362 #ifdef ENOTSUP
00363         else if (errno == ENOTSUP) code = XML_IO_ENOTSUP;
00364 #endif
00365 #ifdef ENOTTY
00366         else if (errno == ENOTTY) code = XML_IO_ENOTTY;
00367 #endif
00368 #ifdef ENXIO
00369         else if (errno == ENXIO) code = XML_IO_ENXIO;
00370 #endif
00371 #ifdef EPERM
00372         else if (errno == EPERM) code = XML_IO_EPERM;
00373 #endif
00374 #ifdef EPIPE
00375         else if (errno == EPIPE) code = XML_IO_EPIPE;
00376 #endif
00377 #ifdef ERANGE
00378         else if (errno == ERANGE) code = XML_IO_ERANGE;
00379 #endif
00380 #ifdef EROFS
00381         else if (errno == EROFS) code = XML_IO_EROFS;
00382 #endif
00383 #ifdef ESPIPE
00384         else if (errno == ESPIPE) code = XML_IO_ESPIPE;
00385 #endif
00386 #ifdef ESRCH
00387         else if (errno == ESRCH) code = XML_IO_ESRCH;
00388 #endif
00389 #ifdef ETIMEDOUT
00390         else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
00391 #endif
00392 #ifdef EXDEV
00393         else if (errno == EXDEV) code = XML_IO_EXDEV;
00394 #endif
00395 #ifdef ENOTSOCK
00396         else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK;
00397 #endif
00398 #ifdef EISCONN
00399         else if (errno == EISCONN) code = XML_IO_EISCONN;
00400 #endif
00401 #ifdef ECONNREFUSED
00402         else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
00403 #endif
00404 #ifdef ETIMEDOUT
00405         else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
00406 #endif
00407 #ifdef ENETUNREACH
00408         else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH;
00409 #endif
00410 #ifdef EADDRINUSE
00411         else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE;
00412 #endif
00413 #ifdef EINPROGRESS
00414         else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS;
00415 #endif
00416 #ifdef EALREADY
00417         else if (errno == EALREADY) code = XML_IO_EALREADY;
00418 #endif
00419 #ifdef EAFNOSUPPORT
00420         else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
00421 #endif
00422         else code = XML_IO_UNKNOWN;
00423 #endif /* HAVE_ERRNO_H */
00424     }
00425     idx = 0;
00426     if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN;
00427     if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0;
00428 
00429     __xmlSimpleError(domain, code, NULL, IOerr[idx], extra);
00430 }
00431 
00439 static void
00440 xmlIOErr(int code, const char *extra)
00441 {
00442     __xmlIOErr(XML_FROM_IO, code, extra);
00443 }
00444 
00452 void
00453 __xmlLoaderErr(void *ctx, const char *msg, const char *filename)
00454 {
00455     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00456     xmlStructuredErrorFunc schannel = NULL;
00457     xmlGenericErrorFunc channel = NULL;
00458     void *data = NULL;
00459     xmlErrorLevel level = XML_ERR_ERROR;
00460 
00461     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00462         (ctxt->instate == XML_PARSER_EOF))
00463     return;
00464     if ((ctxt != NULL) && (ctxt->sax != NULL)) {
00465         if (ctxt->validate) {
00466         channel = ctxt->sax->error;
00467         level = XML_ERR_ERROR;
00468     } else {
00469         channel = ctxt->sax->warning;
00470         level = XML_ERR_WARNING;
00471     }
00472     if (ctxt->sax->initialized == XML_SAX2_MAGIC)
00473         schannel = ctxt->sax->serror;
00474     data = ctxt->userData;
00475     }
00476     __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO,
00477                     XML_IO_LOAD_ERROR, level, NULL, 0,
00478             filename, NULL, NULL, 0, 0,
00479             msg, filename);
00480 
00481 }
00482 
00483 /************************************************************************
00484  *                                  *
00485  *      Tree memory error handler               *
00486  *                                  *
00487  ************************************************************************/
00497 xmlChar *
00498 xmlNormalizeWindowsPath(const xmlChar *path)
00499 {
00500     return xmlCanonicPath(path);
00501 }
00502 
00509 void
00510 xmlCleanupInputCallbacks(void)
00511 {
00512     int i;
00513 
00514     if (!xmlInputCallbackInitialized)
00515         return;
00516 
00517     for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
00518         xmlInputCallbackTable[i].matchcallback = NULL;
00519         xmlInputCallbackTable[i].opencallback = NULL;
00520         xmlInputCallbackTable[i].readcallback = NULL;
00521         xmlInputCallbackTable[i].closecallback = NULL;
00522     }
00523 
00524     xmlInputCallbackNr = 0;
00525     xmlInputCallbackInitialized = 0;
00526 }
00527 
00536 int
00537 xmlPopInputCallbacks(void)
00538 {
00539     if (!xmlInputCallbackInitialized)
00540         return(-1);
00541 
00542     if (xmlInputCallbackNr <= 0)
00543         return(-1);
00544 
00545     xmlInputCallbackNr--;
00546     xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL;
00547     xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL;
00548     xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL;
00549     xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL;
00550 
00551     return(xmlInputCallbackNr);
00552 }
00553 
00554 #ifdef LIBXML_OUTPUT_ENABLED
00555 
00561 void
00562 xmlCleanupOutputCallbacks(void)
00563 {
00564     int i;
00565 
00566     if (!xmlOutputCallbackInitialized)
00567         return;
00568 
00569     for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
00570         xmlOutputCallbackTable[i].matchcallback = NULL;
00571         xmlOutputCallbackTable[i].opencallback = NULL;
00572         xmlOutputCallbackTable[i].writecallback = NULL;
00573         xmlOutputCallbackTable[i].closecallback = NULL;
00574     }
00575 
00576     xmlOutputCallbackNr = 0;
00577     xmlOutputCallbackInitialized = 0;
00578 }
00579 #endif /* LIBXML_OUTPUT_ENABLED */
00580 
00581 /************************************************************************
00582  *                                  *
00583  *      Standard I/O for file accesses              *
00584  *                                  *
00585  ************************************************************************/
00586 
00587 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
00588 
00597 static FILE*
00598 xmlWrapOpenUtf8(const char *path,int mode)
00599 {
00600     FILE *fd = NULL;
00601     wchar_t *wPath;
00602 
00603     wPath = __xmlIOWin32UTF8ToWChar(path);
00604     if(wPath)
00605     {
00606        fd = _wfopen(wPath, mode ? L"wb" : L"rb");
00607        xmlFree(wPath);
00608     }
00609     /* maybe path in native encoding */
00610     if(fd == NULL)
00611        fd = fopen(path, mode ? "wb" : "rb");
00612 
00613     return fd;
00614 }
00615 
00616 #ifdef HAVE_ZLIB_H
00617 static gzFile
00618 xmlWrapGzOpenUtf8(const char *path, const char *mode)
00619 {
00620     gzFile fd;
00621     wchar_t *wPath;
00622 
00623     fd = gzopen (path, mode);
00624     if (fd)
00625         return fd;
00626 
00627     wPath = __xmlIOWin32UTF8ToWChar(path);
00628     if(wPath)
00629     {
00630     int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR);
00631 #ifdef _O_BINARY
00632         m |= (strstr(mode, "b") ? _O_BINARY : 0);
00633 #endif
00634     d = _wopen(wPath, m);
00635     if (d >= 0)
00636         fd = gzdopen(d, mode);
00637         xmlFree(wPath);
00638     }
00639 
00640     return fd;
00641 }
00642 #endif
00643 
00652 static int
00653 xmlWrapStatUtf8(const char *path,struct stat *info)
00654 {
00655 #ifdef HAVE_STAT
00656     int retval = -1;
00657     wchar_t *wPath;
00658 
00659     wPath = __xmlIOWin32UTF8ToWChar(path);
00660     if (wPath)
00661     {
00662        retval = _wstat(wPath,info);
00663        xmlFree(wPath);
00664     }
00665     /* maybe path in native encoding */
00666     if(retval < 0)
00667        retval = stat(path,info);
00668     return retval;
00669 #else
00670     return -1;
00671 #endif
00672 }
00673 
00682 static FILE*
00683 xmlWrapOpenNative(const char *path,int mode)
00684 {
00685     return fopen(path,mode ? "wb" : "rb");
00686 }
00687 
00696 static int
00697 xmlWrapStatNative(const char *path,struct stat *info)
00698 {
00699 #ifdef HAVE_STAT
00700     return stat(path,info);
00701 #else
00702     return -1;
00703 #endif
00704 }
00705 
00706 typedef int (* xmlWrapStatFunc) (const char *f, struct stat *s);
00707 static xmlWrapStatFunc xmlWrapStat = xmlWrapStatNative;
00708 typedef FILE* (* xmlWrapOpenFunc)(const char *f,int mode);
00709 static xmlWrapOpenFunc xmlWrapOpen = xmlWrapOpenNative;
00710 #ifdef HAVE_ZLIB_H
00711 typedef gzFile (* xmlWrapGzOpenFunc) (const char *f, const char *mode);
00712 static xmlWrapGzOpenFunc xmlWrapGzOpen = gzopen;
00713 #endif
00714 
00719 static void
00720 xmlInitPlatformSpecificIo(void)
00721 {
00722     static int xmlPlatformIoInitialized = 0;
00723     OSVERSIONINFO osvi;
00724 
00725     if(xmlPlatformIoInitialized)
00726       return;
00727 
00728     osvi.dwOSVersionInfoSize = sizeof(osvi);
00729 
00730     if(GetVersionEx(&osvi) && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
00731       xmlWrapStat = xmlWrapStatUtf8;
00732       xmlWrapOpen = xmlWrapOpenUtf8;
00733 #ifdef HAVE_ZLIB_H
00734       xmlWrapGzOpen = xmlWrapGzOpenUtf8;
00735 #endif
00736     } else {
00737       xmlWrapStat = xmlWrapStatNative;
00738       xmlWrapOpen = xmlWrapOpenNative;
00739 #ifdef HAVE_ZLIB_H
00740       xmlWrapGzOpen = gzopen;
00741 #endif
00742     }
00743 
00744     xmlPlatformIoInitialized = 1;
00745     return;
00746 }
00747 
00748 #endif
00749 
00764 int
00765 xmlCheckFilename (const char *path)
00766 {
00767 #ifdef HAVE_STAT
00768     struct stat stat_buffer;
00769 #endif
00770     if (path == NULL)
00771         return(0);
00772 
00773 #ifdef HAVE_STAT
00774 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
00775     if (xmlWrapStat(path, &stat_buffer) == -1)
00776         return 0;
00777 #else
00778     if (stat(path, &stat_buffer) == -1)
00779         return 0;
00780 #endif
00781 #ifdef S_ISDIR
00782     if (S_ISDIR(stat_buffer.st_mode))
00783         return 2;
00784 #endif
00785 #endif /* HAVE_STAT */
00786     return 1;
00787 }
00788 
00789 static int
00790 xmlNop(void) {
00791     return(0);
00792 }
00793 
00804 static int
00805 xmlFdRead (void * context, char * buffer, int len) {
00806     int ret;
00807 
00808     ret = read((int) (long) context, &buffer[0], len);
00809     if (ret < 0) xmlIOErr(0, "read()");
00810     return(ret);
00811 }
00812 
00813 #ifdef LIBXML_OUTPUT_ENABLED
00814 
00824 static int
00825 xmlFdWrite (void * context, const char * buffer, int len) {
00826     int ret = 0;
00827 
00828     if (len > 0) {
00829     ret = write((int) (long) context, &buffer[0], len);
00830     if (ret < 0) xmlIOErr(0, "write()");
00831     }
00832     return(ret);
00833 }
00834 #endif /* LIBXML_OUTPUT_ENABLED */
00835 
00844 static int
00845 xmlFdClose (void * context) {
00846     int ret;
00847     ret = close((int) (long) context);
00848     if (ret < 0) xmlIOErr(0, "close()");
00849     return(ret);
00850 }
00851 
00860 int
00861 xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
00862     return(1);
00863 }
00864 
00874 static void *
00875 xmlFileOpen_real (const char *filename) {
00876     const char *path = NULL;
00877     FILE *fd;
00878 
00879     if (filename == NULL)
00880         return(NULL);
00881 
00882     if (!strcmp(filename, "-")) {
00883     fd = stdin;
00884     return((void *) fd);
00885     }
00886 
00887     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
00888 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
00889     path = &filename[17];
00890 #else
00891     path = &filename[16];
00892 #endif
00893     } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
00894 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
00895     path = &filename[8];
00896 #else
00897     path = &filename[7];
00898 #endif
00899     } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) {
00900         /* lots of generators seems to lazy to read RFC 1738 */
00901 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
00902     path = &filename[6];
00903 #else
00904     path = &filename[5];
00905 #endif
00906     } else
00907     path = filename;
00908 
00909     if (path == NULL)
00910     return(NULL);
00911     if (!xmlCheckFilename(path))
00912         return(NULL);
00913 
00914 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
00915     fd = xmlWrapOpen(path, 0);
00916 #else
00917     fd = fopen(path, "r");
00918 #endif /* WIN32 */
00919     if (fd == NULL) xmlIOErr(0, path);
00920     return((void *) fd);
00921 }
00922 
00932 void *
00933 xmlFileOpen (const char *filename) {
00934     char *unescaped;
00935     void *retval;
00936 
00937     retval = xmlFileOpen_real(filename);
00938     if (retval == NULL) {
00939     unescaped = xmlURIUnescapeString(filename, 0, NULL);
00940     if (unescaped != NULL) {
00941         retval = xmlFileOpen_real(unescaped);
00942         xmlFree(unescaped);
00943     }
00944     }
00945 
00946     return retval;
00947 }
00948 
00949 #ifdef LIBXML_OUTPUT_ENABLED
00950 
00959 static void *
00960 xmlFileOpenW (const char *filename) {
00961     const char *path = NULL;
00962     FILE *fd;
00963 
00964     if (!strcmp(filename, "-")) {
00965     fd = stdout;
00966     return((void *) fd);
00967     }
00968 
00969     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
00970 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
00971     path = &filename[17];
00972 #else
00973     path = &filename[16];
00974 #endif
00975     else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
00976 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
00977     path = &filename[8];
00978 #else
00979     path = &filename[7];
00980 #endif
00981     } else
00982     path = filename;
00983 
00984     if (path == NULL)
00985     return(NULL);
00986 
00987 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
00988     fd = xmlWrapOpen(path, 1);
00989 #else
00990        fd = fopen(path, "wb");
00991 #endif /* WIN32 */
00992 
00993      if (fd == NULL) xmlIOErr(0, path);
00994     return((void *) fd);
00995 }
00996 #endif /* LIBXML_OUTPUT_ENABLED */
00997 
01008 int
01009 xmlFileRead (void * context, char * buffer, int len) {
01010     int ret;
01011     if ((context == NULL) || (buffer == NULL))
01012         return(-1);
01013     ret = fread(&buffer[0], 1,  len, (FILE *) context);
01014     if (ret < 0) xmlIOErr(0, "fread()");
01015     return(ret);
01016 }
01017 
01018 #ifdef LIBXML_OUTPUT_ENABLED
01019 
01029 static int
01030 xmlFileWrite (void * context, const char * buffer, int len) {
01031     int items;
01032 
01033     if ((context == NULL) || (buffer == NULL))
01034         return(-1);
01035     items = fwrite(&buffer[0], len, 1, (FILE *) context);
01036     if ((items == 0) && (ferror((FILE *) context))) {
01037         xmlIOErr(0, "fwrite()");
01038     return(-1);
01039     }
01040     return(items * len);
01041 }
01042 #endif /* LIBXML_OUTPUT_ENABLED */
01043 
01052 int
01053 xmlFileClose (void * context) {
01054     FILE *fil;
01055     int ret;
01056 
01057     if (context == NULL)
01058         return(-1);
01059     fil = (FILE *) context;
01060     if ((fil == stdout) || (fil == stderr)) {
01061         ret = fflush(fil);
01062     if (ret < 0)
01063         xmlIOErr(0, "fflush()");
01064     return(0);
01065     }
01066     if (fil == stdin)
01067     return(0);
01068     ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0;
01069     if (ret < 0)
01070         xmlIOErr(0, "fclose()");
01071     return(ret);
01072 }
01073 
01080 static int
01081 xmlFileFlush (void * context) {
01082     int ret;
01083 
01084     if (context == NULL)
01085         return(-1);
01086     ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0;
01087     if (ret < 0)
01088         xmlIOErr(0, "fflush()");
01089     return(ret);
01090 }
01091 
01092 #ifdef LIBXML_OUTPUT_ENABLED
01093 
01103 static int
01104 xmlBufferWrite (void * context, const char * buffer, int len) {
01105     int ret;
01106 
01107     ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
01108     if (ret != 0)
01109         return(-1);
01110     return(len);
01111 }
01112 #endif
01113 
01114 #ifdef HAVE_ZLIB_H
01115 /************************************************************************
01116  *                                  *
01117  *      I/O for compressed file accesses            *
01118  *                                  *
01119  ************************************************************************/
01128 static int
01129 xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) {
01130     return(1);
01131 }
01132 
01142 static void *
01143 xmlGzfileOpen_real (const char *filename) {
01144     const char *path = NULL;
01145     gzFile fd;
01146 
01147     if (!strcmp(filename, "-")) {
01148         fd = gzdopen(dup(0), "rb");
01149     return((void *) fd);
01150     }
01151 
01152     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
01153 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
01154     path = &filename[17];
01155 #else
01156     path = &filename[16];
01157 #endif
01158     else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
01159 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
01160     path = &filename[8];
01161 #else
01162     path = &filename[7];
01163 #endif
01164     } else
01165     path = filename;
01166 
01167     if (path == NULL)
01168     return(NULL);
01169     if (!xmlCheckFilename(path))
01170         return(NULL);
01171 
01172 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
01173     fd = xmlWrapGzOpen(path, "rb");
01174 #else
01175     fd = gzopen(path, "rb");
01176 #endif
01177     return((void *) fd);
01178 }
01179 
01187 static void *
01188 xmlGzfileOpen (const char *filename) {
01189     char *unescaped;
01190     void *retval;
01191 
01192     retval = xmlGzfileOpen_real(filename);
01193     if (retval == NULL) {
01194     unescaped = xmlURIUnescapeString(filename, 0, NULL);
01195     if (unescaped != NULL) {
01196         retval = xmlGzfileOpen_real(unescaped);
01197     }
01198     xmlFree(unescaped);
01199     }
01200     return retval;
01201 }
01202 
01203 #ifdef LIBXML_OUTPUT_ENABLED
01204 
01214 static void *
01215 xmlGzfileOpenW (const char *filename, int compression) {
01216     const char *path = NULL;
01217     char mode[15];
01218     gzFile fd;
01219 
01220     snprintf(mode, sizeof(mode), "wb%d", compression);
01221     if (!strcmp(filename, "-")) {
01222         fd = gzdopen(dup(1), mode);
01223     return((void *) fd);
01224     }
01225 
01226     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17))
01227 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
01228     path = &filename[17];
01229 #else
01230     path = &filename[16];
01231 #endif
01232     else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) {
01233 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
01234     path = &filename[8];
01235 #else
01236     path = &filename[7];
01237 #endif
01238     } else
01239     path = filename;
01240 
01241     if (path == NULL)
01242     return(NULL);
01243 
01244 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
01245     fd = xmlWrapGzOpen(path, mode);
01246 #else
01247     fd = gzopen(path, mode);
01248 #endif
01249     return((void *) fd);
01250 }
01251 #endif /* LIBXML_OUTPUT_ENABLED */
01252 
01263 static int
01264 xmlGzfileRead (void * context, char * buffer, int len) {
01265     int ret;
01266 
01267     ret = gzread((gzFile) context, &buffer[0], len);
01268     if (ret < 0) xmlIOErr(0, "gzread()");
01269     return(ret);
01270 }
01271 
01272 #ifdef LIBXML_OUTPUT_ENABLED
01273 
01283 static int
01284 xmlGzfileWrite (void * context, const char * buffer, int len) {
01285     int ret;
01286 
01287     ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
01288     if (ret < 0) xmlIOErr(0, "gzwrite()");
01289     return(ret);
01290 }
01291 #endif /* LIBXML_OUTPUT_ENABLED */
01292 
01299 static int
01300 xmlGzfileClose (void * context) {
01301     int ret;
01302 
01303     ret =  (gzclose((gzFile) context) == Z_OK ) ? 0 : -1;
01304     if (ret < 0) xmlIOErr(0, "gzclose()");
01305     return(ret);
01306 }
01307 #endif /* HAVE_ZLIB_H */
01308 
01309 #ifdef LIBXML_HTTP_ENABLED
01310 /************************************************************************
01311  *                                  *
01312  *          I/O for HTTP file accesses          *
01313  *                                  *
01314  ************************************************************************/
01315 
01316 #ifdef LIBXML_OUTPUT_ENABLED
01317 typedef struct xmlIOHTTPWriteCtxt_
01318 {
01319     int         compression;
01320 
01321     char *      uri;
01322 
01323     void *      doc_buff;
01324 
01325 } xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr;
01326 
01327 #ifdef HAVE_ZLIB_H
01328 
01329 #define DFLT_WBITS      ( -15 )
01330 #define DFLT_MEM_LVL        ( 8 )
01331 #define GZ_MAGIC1       ( 0x1f )
01332 #define GZ_MAGIC2       ( 0x8b )
01333 #define LXML_ZLIB_OS_CODE   ( 0x03 )
01334 #define INIT_HTTP_BUFF_SIZE ( 32768 )
01335 #define DFLT_ZLIB_RATIO     ( 5 )
01336 
01337 /*
01338 **  Data structure and functions to work with sending compressed data
01339 **  via HTTP.
01340 */
01341 
01342 typedef struct xmlZMemBuff_
01343 {
01344    unsigned long    size;
01345    unsigned long    crc;
01346 
01347    unsigned char *  zbuff;
01348    z_stream     zctrl;
01349 
01350 } xmlZMemBuff, *xmlZMemBuffPtr;
01351 
01360 static void
01361 append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) {
01362 
01363     int     idx;
01364 
01365     if ( buff == NULL )
01366     return;
01367 
01368     /*
01369     **  This is plagiarized from putLong in gzio.c (zlib source) where
01370     **  the number "4" is hardcoded.  If zlib is ever patched to
01371     **  support 64 bit file sizes, this code would need to be patched
01372     **  as well.
01373     */
01374 
01375     for ( idx = 0; idx < 4; idx++ ) {
01376     *buff->zctrl.next_out = ( data & 0xff );
01377     data >>= 8;
01378     buff->zctrl.next_out++;
01379     }
01380 
01381     return;
01382 }
01383 
01391 static void
01392 xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
01393 
01394 #ifdef DEBUG_HTTP
01395     int z_err;
01396 #endif
01397 
01398     if ( buff == NULL )
01399     return;
01400 
01401     xmlFree( buff->zbuff );
01402 #ifdef DEBUG_HTTP
01403     z_err = deflateEnd( &buff->zctrl );
01404     if ( z_err != Z_OK )
01405     xmlGenericError( xmlGenericErrorContext,
01406             "xmlFreeZMemBuff:  Error releasing zlib context:  %d\n",
01407             z_err );
01408 #else
01409     deflateEnd( &buff->zctrl );
01410 #endif
01411 
01412     xmlFree( buff );
01413     return;
01414 }
01415 
01426 static void *
01427 xmlCreateZMemBuff( int compression ) {
01428 
01429     int         z_err;
01430     int         hdr_lgth;
01431     xmlZMemBuffPtr  buff = NULL;
01432 
01433     if ( ( compression < 1 ) || ( compression > 9 ) )
01434     return ( NULL );
01435 
01436     /*  Create the control and data areas  */
01437 
01438     buff = xmlMalloc( sizeof( xmlZMemBuff ) );
01439     if ( buff == NULL ) {
01440     xmlIOErrMemory("creating buffer context");
01441     return ( NULL );
01442     }
01443 
01444     (void)memset( buff, 0, sizeof( xmlZMemBuff ) );
01445     buff->size = INIT_HTTP_BUFF_SIZE;
01446     buff->zbuff = xmlMalloc( buff->size );
01447     if ( buff->zbuff == NULL ) {
01448     xmlFreeZMemBuff( buff );
01449     xmlIOErrMemory("creating buffer");
01450     return ( NULL );
01451     }
01452 
01453     z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED,
01454                 DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY );
01455     if ( z_err != Z_OK ) {
01456     xmlChar msg[500];
01457     xmlFreeZMemBuff( buff );
01458     buff = NULL;
01459     xmlStrPrintf(msg, 500,
01460             (const xmlChar *) "xmlCreateZMemBuff:  %s %d\n",
01461             "Error initializing compression context.  ZLIB error:",
01462             z_err );
01463     xmlIOErr(XML_IO_WRITE, (const char *) msg);
01464     return ( NULL );
01465     }
01466 
01467     /*  Set the header data.  The CRC will be needed for the trailer  */
01468     buff->crc = crc32( 0L, NULL, 0 );
01469     hdr_lgth = snprintf( (char *)buff->zbuff, buff->size,
01470             "%c%c%c%c%c%c%c%c%c%c",
01471             GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED,
01472             0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE );
01473     buff->zctrl.next_out  = buff->zbuff + hdr_lgth;
01474     buff->zctrl.avail_out = buff->size - hdr_lgth;
01475 
01476     return ( buff );
01477 }
01478 
01490 static int
01491 xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) {
01492 
01493     int         rc = -1;
01494     size_t      new_size;
01495     size_t      cur_used;
01496 
01497     unsigned char * tmp_ptr = NULL;
01498 
01499     if ( buff == NULL )
01500     return ( -1 );
01501 
01502     else if ( ext_amt == 0 )
01503     return ( 0 );
01504 
01505     cur_used = buff->zctrl.next_out - buff->zbuff;
01506     new_size = buff->size + ext_amt;
01507 
01508 #ifdef DEBUG_HTTP
01509     if ( cur_used > new_size )
01510     xmlGenericError( xmlGenericErrorContext,
01511             "xmlZMemBuffExtend:  %s\n%s %d bytes.\n",
01512             "Buffer overwrite detected during compressed memory",
01513             "buffer extension.  Overflowed by",
01514             (cur_used - new_size ) );
01515 #endif
01516 
01517     tmp_ptr = xmlRealloc( buff->zbuff, new_size );
01518     if ( tmp_ptr != NULL ) {
01519     rc = 0;
01520     buff->size  = new_size;
01521     buff->zbuff = tmp_ptr;
01522     buff->zctrl.next_out  = tmp_ptr + cur_used;
01523     buff->zctrl.avail_out = new_size - cur_used;
01524     }
01525     else {
01526     xmlChar msg[500];
01527     xmlStrPrintf(msg, 500,
01528             (const xmlChar *) "xmlZMemBuffExtend:  %s %lu bytes.\n",
01529             "Allocation failure extending output buffer to",
01530             new_size );
01531     xmlIOErr(XML_IO_WRITE, (const char *) msg);
01532     }
01533 
01534     return ( rc );
01535 }
01536 
01548 static int
01549 xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) {
01550 
01551     int     z_err;
01552     size_t  min_accept;
01553 
01554     if ( ( buff == NULL ) || ( src == NULL ) )
01555     return ( -1 );
01556 
01557     buff->zctrl.avail_in = len;
01558     buff->zctrl.next_in  = (unsigned char *)src;
01559     while ( buff->zctrl.avail_in > 0 ) {
01560     /*
01561     **  Extend the buffer prior to deflate call if a reasonable amount
01562     **  of output buffer space is not available.
01563     */
01564     min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO;
01565     if ( buff->zctrl.avail_out <= min_accept ) {
01566         if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
01567         return ( -1 );
01568     }
01569 
01570     z_err = deflate( &buff->zctrl, Z_NO_FLUSH );
01571     if ( z_err != Z_OK ) {
01572         xmlChar msg[500];
01573         xmlStrPrintf(msg, 500,
01574             (const xmlChar *) "xmlZMemBuffAppend:  %s %d %s - %d",
01575             "Compression error while appending",
01576             len, "bytes to buffer.  ZLIB error", z_err );
01577         xmlIOErr(XML_IO_WRITE, (const char *) msg);
01578         return ( -1 );
01579     }
01580     }
01581 
01582     buff->crc = crc32( buff->crc, (unsigned char *)src, len );
01583 
01584     return ( len );
01585 }
01586 
01598 static int
01599 xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) {
01600 
01601     int     zlgth = -1;
01602     int     z_err;
01603 
01604     if ( ( buff == NULL ) || ( data_ref == NULL ) )
01605     return ( -1 );
01606 
01607     /*  Need to loop until compression output buffers are flushed  */
01608 
01609     do
01610     {
01611     z_err = deflate( &buff->zctrl, Z_FINISH );
01612     if ( z_err == Z_OK ) {
01613         /*  In this case Z_OK means more buffer space needed  */
01614 
01615         if ( xmlZMemBuffExtend( buff, buff->size ) == -1 )
01616         return ( -1 );
01617     }
01618     }
01619     while ( z_err == Z_OK );
01620 
01621     /*  If the compression state is not Z_STREAM_END, some error occurred  */
01622 
01623     if ( z_err == Z_STREAM_END ) {
01624 
01625     /*  Need to append the gzip data trailer  */
01626 
01627     if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) {
01628         if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 )
01629         return ( -1 );
01630     }
01631 
01632     /*
01633     **  For whatever reason, the CRC and length data are pushed out
01634     **  in reverse byte order.  So a memcpy can't be used here.
01635     */
01636 
01637     append_reverse_ulong( buff, buff->crc );
01638     append_reverse_ulong( buff, buff->zctrl.total_in );
01639 
01640     zlgth = buff->zctrl.next_out - buff->zbuff;
01641     *data_ref = (char *)buff->zbuff;
01642     }
01643 
01644     else {
01645     xmlChar msg[500];
01646     xmlStrPrintf(msg, 500,
01647             (const xmlChar *) "xmlZMemBuffGetContent:  %s - %d\n",
01648             "Error flushing zlib buffers.  Error code", z_err );
01649     xmlIOErr(XML_IO_WRITE, (const char *) msg);
01650     }
01651 
01652     return ( zlgth );
01653 }
01654 #endif /* LIBXML_OUTPUT_ENABLED */
01655 #endif  /*  HAVE_ZLIB_H  */
01656 
01657 #ifdef LIBXML_OUTPUT_ENABLED
01658 
01666 static void
01667 xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt )
01668 {
01669     if ( ctxt->uri != NULL )
01670     xmlFree( ctxt->uri );
01671 
01672     if ( ctxt->doc_buff != NULL ) {
01673 
01674 #ifdef HAVE_ZLIB_H
01675     if ( ctxt->compression > 0 ) {
01676         xmlFreeZMemBuff( ctxt->doc_buff );
01677     }
01678     else
01679 #endif
01680     {
01681         xmlOutputBufferClose( ctxt->doc_buff );
01682     }
01683     }
01684 
01685     xmlFree( ctxt );
01686     return;
01687 }
01688 #endif /* LIBXML_OUTPUT_ENABLED */
01689 
01690 
01699 int
01700 xmlIOHTTPMatch (const char *filename) {
01701     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
01702     return(1);
01703     return(0);
01704 }
01705 
01714 void *
01715 xmlIOHTTPOpen (const char *filename) {
01716     return(xmlNanoHTTPOpen(filename, NULL));
01717 }
01718 
01719 #ifdef LIBXML_OUTPUT_ENABLED
01720 
01731 void *
01732 xmlIOHTTPOpenW(const char *post_uri, int compression)
01733 {
01734 
01735     xmlIOHTTPWriteCtxtPtr ctxt = NULL;
01736 
01737     if (post_uri == NULL)
01738         return (NULL);
01739 
01740     ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt));
01741     if (ctxt == NULL) {
01742     xmlIOErrMemory("creating HTTP output context");
01743         return (NULL);
01744     }
01745 
01746     (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt));
01747 
01748     ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri);
01749     if (ctxt->uri == NULL) {
01750     xmlIOErrMemory("copying URI");
01751         xmlFreeHTTPWriteCtxt(ctxt);
01752         return (NULL);
01753     }
01754 
01755     /*
01756      * **  Since the document length is required for an HTTP post,
01757      * **  need to put the document into a buffer.  A memory buffer
01758      * **  is being used to avoid pushing the data to disk and back.
01759      */
01760 
01761 #ifdef HAVE_ZLIB_H
01762     if ((compression > 0) && (compression <= 9)) {
01763 
01764         ctxt->compression = compression;
01765         ctxt->doc_buff = xmlCreateZMemBuff(compression);
01766     } else
01767 #endif
01768     {
01769         /*  Any character conversions should have been done before this  */
01770 
01771         ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL);
01772     }
01773 
01774     if (ctxt->doc_buff == NULL) {
01775         xmlFreeHTTPWriteCtxt(ctxt);
01776         ctxt = NULL;
01777     }
01778 
01779     return (ctxt);
01780 }
01781 #endif /* LIBXML_OUTPUT_ENABLED */
01782 
01783 #ifdef LIBXML_OUTPUT_ENABLED
01784 
01794 static void *
01795 xmlIOHTTPDfltOpenW( const char * post_uri ) {
01796     return ( xmlIOHTTPOpenW( post_uri, 0 ) );
01797 }
01798 #endif /* LIBXML_OUTPUT_ENABLED */
01799 
01810 int
01811 xmlIOHTTPRead(void * context, char * buffer, int len) {
01812     if ((buffer == NULL) || (len < 0)) return(-1);
01813     return(xmlNanoHTTPRead(context, &buffer[0], len));
01814 }
01815 
01816 #ifdef LIBXML_OUTPUT_ENABLED
01817 
01829 static int
01830 xmlIOHTTPWrite( void * context, const char * buffer, int len ) {
01831 
01832     xmlIOHTTPWriteCtxtPtr   ctxt = context;
01833 
01834     if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) )
01835     return ( -1 );
01836 
01837     if ( len > 0 ) {
01838 
01839     /*  Use gzwrite or fwrite as previously setup in the open call  */
01840 
01841 #ifdef HAVE_ZLIB_H
01842     if ( ctxt->compression > 0 )
01843         len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len );
01844 
01845     else
01846 #endif
01847         len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer );
01848 
01849     if ( len < 0 ) {
01850         xmlChar msg[500];
01851         xmlStrPrintf(msg, 500,
01852             (const xmlChar *) "xmlIOHTTPWrite:  %s\n%s '%s'.\n",
01853             "Error appending to internal buffer.",
01854             "Error sending document to URI",
01855             ctxt->uri );
01856         xmlIOErr(XML_IO_WRITE, (const char *) msg);
01857     }
01858     }
01859 
01860     return ( len );
01861 }
01862 #endif /* LIBXML_OUTPUT_ENABLED */
01863 
01864 
01873 int
01874 xmlIOHTTPClose (void * context) {
01875     xmlNanoHTTPClose(context);
01876     return 0;
01877 }
01878 
01879 #ifdef LIBXML_OUTPUT_ENABLED
01880 
01887 static int
01888 xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
01889 
01890     int             close_rc = -1;
01891     int             http_rtn = 0;
01892     int             content_lgth = 0;
01893     xmlIOHTTPWriteCtxtPtr   ctxt = context;
01894 
01895     char *          http_content = NULL;
01896     char *          content_encoding = NULL;
01897     char *          content_type = (char *) "text/xml";
01898     void *          http_ctxt = NULL;
01899 
01900     if ( ( ctxt == NULL ) || ( http_mthd == NULL ) )
01901     return ( -1 );
01902 
01903     /*  Retrieve the content from the appropriate buffer  */
01904 
01905 #ifdef HAVE_ZLIB_H
01906 
01907     if ( ctxt->compression > 0 ) {
01908     content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content );
01909     content_encoding = (char *) "Content-Encoding: gzip";
01910     }
01911     else
01912 #endif
01913     {
01914     /*  Pull the data out of the memory output buffer  */
01915 
01916     xmlOutputBufferPtr  dctxt = ctxt->doc_buff;
01917     http_content = (char *)dctxt->buffer->content;
01918     content_lgth = dctxt->buffer->use;
01919     }
01920 
01921     if ( http_content == NULL ) {
01922     xmlChar msg[500];
01923     xmlStrPrintf(msg, 500,
01924              (const xmlChar *) "xmlIOHTTPCloseWrite:  %s '%s' %s '%s'.\n",
01925              "Error retrieving content.\nUnable to",
01926              http_mthd, "data to URI", ctxt->uri );
01927     xmlIOErr(XML_IO_WRITE, (const char *) msg);
01928     }
01929 
01930     else {
01931 
01932     http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content,
01933                     &content_type, content_encoding,
01934                     content_lgth );
01935 
01936     if ( http_ctxt != NULL ) {
01937 #ifdef DEBUG_HTTP
01938         /*  If testing/debugging - dump reply with request content  */
01939 
01940         FILE *  tst_file = NULL;
01941         char    buffer[ 4096 ];
01942         char *  dump_name = NULL;
01943         int     avail;
01944 
01945         xmlGenericError( xmlGenericErrorContext,
01946             "xmlNanoHTTPCloseWrite:  HTTP %s to\n%s returned %d.\n",
01947             http_mthd, ctxt->uri,
01948             xmlNanoHTTPReturnCode( http_ctxt ) );
01949 
01950         /*
01951         **  Since either content or reply may be gzipped,
01952         **  dump them to separate files instead of the
01953         **  standard error context.
01954         */
01955 
01956         dump_name = tempnam( NULL, "lxml" );
01957         if ( dump_name != NULL ) {
01958         (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
01959 
01960         tst_file = fopen( buffer, "wb" );
01961         if ( tst_file != NULL ) {
01962             xmlGenericError( xmlGenericErrorContext,
01963             "Transmitted content saved in file:  %s\n", buffer );
01964 
01965             fwrite( http_content, sizeof( char ),
01966                     content_lgth, tst_file );
01967             fclose( tst_file );
01968         }
01969 
01970         (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
01971         tst_file = fopen( buffer, "wb" );
01972         if ( tst_file != NULL ) {
01973             xmlGenericError( xmlGenericErrorContext,
01974             "Reply content saved in file:  %s\n", buffer );
01975 
01976 
01977             while ( (avail = xmlNanoHTTPRead( http_ctxt,
01978                     buffer, sizeof( buffer ) )) > 0 ) {
01979 
01980             fwrite( buffer, sizeof( char ), avail, tst_file );
01981             }
01982 
01983             fclose( tst_file );
01984         }
01985 
01986         free( dump_name );
01987         }
01988 #endif  /*  DEBUG_HTTP  */
01989 
01990         http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
01991         if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
01992         close_rc = 0;
01993         else {
01994                 xmlChar msg[500];
01995                 xmlStrPrintf(msg, 500,
01996     (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n",
01997                 http_mthd, content_lgth,
01998                 "bytes to URI", ctxt->uri,
01999                 "failed.  HTTP return code:", http_rtn );
02000         xmlIOErr(XML_IO_WRITE, (const char *) msg);
02001             }
02002 
02003         xmlNanoHTTPClose( http_ctxt );
02004         xmlFree( content_type );
02005     }
02006     }
02007 
02008     /*  Final cleanups  */
02009 
02010     xmlFreeHTTPWriteCtxt( ctxt );
02011 
02012     return ( close_rc );
02013 }
02014 
02023 static int
02024 xmlIOHTTPClosePut( void * ctxt ) {
02025     return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) );
02026 }
02027 
02028 
02037 static int
02038 xmlIOHTTPClosePost( void * ctxt ) {
02039     return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) );
02040 }
02041 #endif /* LIBXML_OUTPUT_ENABLED */
02042 
02043 #endif /* LIBXML_HTTP_ENABLED */
02044 
02045 #ifdef LIBXML_FTP_ENABLED
02046 /************************************************************************
02047  *                                  *
02048  *          I/O for FTP file accesses           *
02049  *                                  *
02050  ************************************************************************/
02059 int
02060 xmlIOFTPMatch (const char *filename) {
02061     if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6))
02062     return(1);
02063     return(0);
02064 }
02065 
02074 void *
02075 xmlIOFTPOpen (const char *filename) {
02076     return(xmlNanoFTPOpen(filename));
02077 }
02078 
02089 int
02090 xmlIOFTPRead(void * context, char * buffer, int len) {
02091     if ((buffer == NULL) || (len < 0)) return(-1);
02092     return(xmlNanoFTPRead(context, &buffer[0], len));
02093 }
02094 
02103 int
02104 xmlIOFTPClose (void * context) {
02105     return ( xmlNanoFTPClose(context) );
02106 }
02107 #endif /* LIBXML_FTP_ENABLED */
02108 
02109 
02121 int
02122 xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
02123     xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
02124     xmlInputCloseCallback closeFunc) {
02125     if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
02126     return(-1);
02127     }
02128     xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
02129     xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
02130     xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
02131     xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
02132     xmlInputCallbackInitialized = 1;
02133     return(xmlInputCallbackNr++);
02134 }
02135 
02136 #ifdef LIBXML_OUTPUT_ENABLED
02137 
02148 int
02149 xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
02150     xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
02151     xmlOutputCloseCallback closeFunc) {
02152     if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
02153     return(-1);
02154     }
02155     xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
02156     xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
02157     xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
02158     xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
02159     xmlOutputCallbackInitialized = 1;
02160     return(xmlOutputCallbackNr++);
02161 }
02162 #endif /* LIBXML_OUTPUT_ENABLED */
02163 
02169 void
02170 xmlRegisterDefaultInputCallbacks(void) {
02171     if (xmlInputCallbackInitialized)
02172     return;
02173 
02174 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
02175     xmlInitPlatformSpecificIo();
02176 #endif
02177 
02178     xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
02179                           xmlFileRead, xmlFileClose);
02180 #ifdef HAVE_ZLIB_H
02181     xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
02182                           xmlGzfileRead, xmlGzfileClose);
02183 #endif /* HAVE_ZLIB_H */
02184 
02185 #ifdef LIBXML_HTTP_ENABLED
02186     xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
02187                           xmlIOHTTPRead, xmlIOHTTPClose);
02188 #endif /* LIBXML_HTTP_ENABLED */
02189 
02190 #ifdef LIBXML_FTP_ENABLED
02191     xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
02192                           xmlIOFTPRead, xmlIOFTPClose);
02193 #endif /* LIBXML_FTP_ENABLED */
02194     xmlInputCallbackInitialized = 1;
02195 }
02196 
02197 #ifdef LIBXML_OUTPUT_ENABLED
02198 
02203 void
02204 xmlRegisterDefaultOutputCallbacks (void) {
02205     if (xmlOutputCallbackInitialized)
02206     return;
02207 
02208 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
02209     xmlInitPlatformSpecificIo();
02210 #endif
02211 
02212     xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
02213                           xmlFileWrite, xmlFileClose);
02214 
02215 #ifdef LIBXML_HTTP_ENABLED
02216     xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
02217                            xmlIOHTTPWrite, xmlIOHTTPClosePut);
02218 #endif
02219 
02220 /*********************************
02221  No way a-priori to distinguish between gzipped files from
02222  uncompressed ones except opening if existing then closing
02223  and saving with same compression ratio ... a pain.
02224 
02225 #ifdef HAVE_ZLIB_H
02226     xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
02227                            xmlGzfileWrite, xmlGzfileClose);
02228 #endif
02229 
02230  Nor FTP PUT ....
02231 #ifdef LIBXML_FTP_ENABLED
02232     xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
02233                            xmlIOFTPWrite, xmlIOFTPClose);
02234 #endif
02235  **********************************/
02236     xmlOutputCallbackInitialized = 1;
02237 }
02238 
02239 #ifdef LIBXML_HTTP_ENABLED
02240 
02248 void
02249 xmlRegisterHTTPPostCallbacks( void ) {
02250 
02251     /*  Register defaults if not done previously  */
02252 
02253     if ( xmlOutputCallbackInitialized == 0 )
02254     xmlRegisterDefaultOutputCallbacks( );
02255 
02256     xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW,
02257                            xmlIOHTTPWrite, xmlIOHTTPClosePost);
02258     return;
02259 }
02260 #endif
02261 #endif /* LIBXML_OUTPUT_ENABLED */
02262 
02271 xmlParserInputBufferPtr
02272 xmlAllocParserInputBuffer(xmlCharEncoding enc) {
02273     xmlParserInputBufferPtr ret;
02274 
02275     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
02276     if (ret == NULL) {
02277     xmlIOErrMemory("creating input buffer");
02278     return(NULL);
02279     }
02280     memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
02281     ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
02282     if (ret->buffer == NULL) {
02283         xmlFree(ret);
02284     return(NULL);
02285     }
02286     ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
02287     ret->encoder = xmlGetCharEncodingHandler(enc);
02288     if (ret->encoder != NULL)
02289         ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
02290     else
02291         ret->raw = NULL;
02292     ret->readcallback = NULL;
02293     ret->closecallback = NULL;
02294     ret->context = NULL;
02295     ret->compressed = -1;
02296     ret->rawconsumed = 0;
02297 
02298     return(ret);
02299 }
02300 
02301 #ifdef LIBXML_OUTPUT_ENABLED
02302 
02310 xmlOutputBufferPtr
02311 xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
02312     xmlOutputBufferPtr ret;
02313 
02314     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
02315     if (ret == NULL) {
02316     xmlIOErrMemory("creating output buffer");
02317     return(NULL);
02318     }
02319     memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
02320     ret->buffer = xmlBufferCreate();
02321     if (ret->buffer == NULL) {
02322         xmlFree(ret);
02323     return(NULL);
02324     }
02325 
02326     /* try to avoid a performance problem with Windows realloc() */
02327     if (ret->buffer->alloc == XML_BUFFER_ALLOC_EXACT)
02328         ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
02329 
02330     ret->encoder = encoder;
02331     if (encoder != NULL) {
02332         ret->conv = xmlBufferCreateSize(4000);
02333     if (ret->conv == NULL) {
02334         xmlFree(ret);
02335         return(NULL);
02336     }
02337 
02338     /*
02339      * This call is designed to initiate the encoder state
02340      */
02341     xmlCharEncOutFunc(encoder, ret->conv, NULL);
02342     } else
02343         ret->conv = NULL;
02344     ret->writecallback = NULL;
02345     ret->closecallback = NULL;
02346     ret->context = NULL;
02347     ret->written = 0;
02348 
02349     return(ret);
02350 }
02351 
02360 xmlOutputBufferPtr
02361 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
02362     xmlOutputBufferPtr ret;
02363 
02364     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
02365     if (ret == NULL) {
02366     xmlIOErrMemory("creating output buffer");
02367     return(NULL);
02368     }
02369     memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
02370     ret->buffer = xmlBufferCreate();
02371     if (ret->buffer == NULL) {
02372         xmlFree(ret);
02373     return(NULL);
02374     }
02375 
02376 
02377     /*
02378      * For conversion buffers we use the special IO handling
02379      * We don't do that from the exported API to avoid confusing
02380      * user's code.
02381      */
02382     ret->buffer->alloc = XML_BUFFER_ALLOC_IO;
02383     ret->buffer->contentIO = ret->buffer->content;
02384 
02385     ret->encoder = encoder;
02386     if (encoder != NULL) {
02387         ret->conv = xmlBufferCreateSize(4000);
02388     if (ret->conv == NULL) {
02389         xmlFree(ret);
02390         return(NULL);
02391     }
02392 
02393     /*
02394      * This call is designed to initiate the encoder state
02395      */
02396     xmlCharEncOutFunc(encoder, ret->conv, NULL);
02397     } else
02398         ret->conv = NULL;
02399     ret->writecallback = NULL;
02400     ret->closecallback = NULL;
02401     ret->context = NULL;
02402     ret->written = 0;
02403 
02404     return(ret);
02405 }
02406 
02407 #endif /* LIBXML_OUTPUT_ENABLED */
02408 
02415 void
02416 xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
02417     if (in == NULL) return;
02418 
02419     if (in->raw) {
02420         xmlBufferFree(in->raw);
02421     in->raw = NULL;
02422     }
02423     if (in->encoder != NULL) {
02424         xmlCharEncCloseFunc(in->encoder);
02425     }
02426     if (in->closecallback != NULL) {
02427     in->closecallback(in->context);
02428     }
02429     if (in->buffer != NULL) {
02430         xmlBufferFree(in->buffer);
02431     in->buffer = NULL;
02432     }
02433 
02434     xmlFree(in);
02435 }
02436 
02437 #ifdef LIBXML_OUTPUT_ENABLED
02438 
02447 int
02448 xmlOutputBufferClose(xmlOutputBufferPtr out)
02449 {
02450     int written;
02451     int err_rc = 0;
02452 
02453     if (out == NULL)
02454         return (-1);
02455     if (out->writecallback != NULL)
02456         xmlOutputBufferFlush(out);
02457     if (out->closecallback != NULL) {
02458         err_rc = out->closecallback(out->context);
02459     }
02460     written = out->written;
02461     if (out->conv) {
02462         xmlBufferFree(out->conv);
02463         out->conv = NULL;
02464     }
02465     if (out->encoder != NULL) {
02466         xmlCharEncCloseFunc(out->encoder);
02467     }
02468     if (out->buffer != NULL) {
02469         xmlBufferFree(out->buffer);
02470         out->buffer = NULL;
02471     }
02472 
02473     if (out->error)
02474         err_rc = -1;
02475     xmlFree(out);
02476     return ((err_rc == 0) ? written : err_rc);
02477 }
02478 #endif /* LIBXML_OUTPUT_ENABLED */
02479 
02480 xmlParserInputBufferPtr
02481 __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
02482     xmlParserInputBufferPtr ret;
02483     int i = 0;
02484     void *context = NULL;
02485 
02486     if (xmlInputCallbackInitialized == 0)
02487     xmlRegisterDefaultInputCallbacks();
02488 
02489     if (URI == NULL) return(NULL);
02490 
02491     /*
02492      * Try to find one of the input accept method accepting that scheme
02493      * Go in reverse to give precedence to user defined handlers.
02494      */
02495     if (context == NULL) {
02496     for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
02497         if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
02498         (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
02499         context = xmlInputCallbackTable[i].opencallback(URI);
02500         if (context != NULL) {
02501             break;
02502         }
02503         }
02504     }
02505     }
02506     if (context == NULL) {
02507     return(NULL);
02508     }
02509 
02510     /*
02511      * Allocate the Input buffer front-end.
02512      */
02513     ret = xmlAllocParserInputBuffer(enc);
02514     if (ret != NULL) {
02515     ret->context = context;
02516     ret->readcallback = xmlInputCallbackTable[i].readcallback;
02517     ret->closecallback = xmlInputCallbackTable[i].closecallback;
02518 #ifdef HAVE_ZLIB_H
02519     if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) &&
02520         (strcmp(URI, "-") != 0)) {
02521 #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
02522             ret->compressed = !gzdirect(context);
02523 #else
02524         if (((z_stream *)context)->avail_in > 4) {
02525             char *cptr, buff4[4];
02526         cptr = (char *) ((z_stream *)context)->next_in;
02527         if (gzread(context, buff4, 4) == 4) {
02528             if (strncmp(buff4, cptr, 4) == 0)
02529                 ret->compressed = 0;
02530             else
02531                 ret->compressed = 1;
02532             gzrewind(context);
02533         }
02534         }
02535 #endif
02536     }
02537 #endif
02538     }
02539     else
02540       xmlInputCallbackTable[i].closecallback (context);
02541 
02542     return(ret);
02543 }
02544 
02558 xmlParserInputBufferPtr
02559 xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
02560     if ((xmlParserInputBufferCreateFilenameValue)) {
02561         return xmlParserInputBufferCreateFilenameValue(URI, enc);
02562     }
02563     return __xmlParserInputBufferCreateFilename(URI, enc);
02564 }
02565 
02566 #ifdef LIBXML_OUTPUT_ENABLED
02567 xmlOutputBufferPtr
02568 __xmlOutputBufferCreateFilename(const char *URI,
02569                               xmlCharEncodingHandlerPtr encoder,
02570                               int compression ATTRIBUTE_UNUSED) {
02571     xmlOutputBufferPtr ret;
02572     xmlURIPtr puri;
02573     int i = 0;
02574     void *context = NULL;
02575     char *unescaped = NULL;
02576 #ifdef HAVE_ZLIB_H
02577     int is_file_uri = 1;
02578 #endif
02579 
02580     if (xmlOutputCallbackInitialized == 0)
02581     xmlRegisterDefaultOutputCallbacks();
02582 
02583     if (URI == NULL) return(NULL);
02584 
02585     puri = xmlParseURI(URI);
02586     if (puri != NULL) {
02587 #ifdef HAVE_ZLIB_H
02588         if ((puri->scheme != NULL) &&
02589         (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
02590         is_file_uri = 0;
02591 #endif
02592     /*
02593      * try to limit the damages of the URI unescaping code.
02594      */
02595     if ((puri->scheme == NULL) ||
02596         (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file")))
02597         unescaped = xmlURIUnescapeString(URI, 0, NULL);
02598     xmlFreeURI(puri);
02599     }
02600 
02601     /*
02602      * Try to find one of the output accept method accepting that scheme
02603      * Go in reverse to give precedence to user defined handlers.
02604      * try with an unescaped version of the URI
02605      */
02606     if (unescaped != NULL) {
02607 #ifdef HAVE_ZLIB_H
02608     if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
02609         context = xmlGzfileOpenW(unescaped, compression);
02610         if (context != NULL) {
02611         ret = xmlAllocOutputBufferInternal(encoder);
02612         if (ret != NULL) {
02613             ret->context = context;
02614             ret->writecallback = xmlGzfileWrite;
02615             ret->closecallback = xmlGzfileClose;
02616         }
02617         xmlFree(unescaped);
02618         return(ret);
02619         }
02620     }
02621 #endif
02622     for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
02623         if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
02624         (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) {
02625 #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
02626         /*  Need to pass compression parameter into HTTP open calls  */
02627         if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
02628             context = xmlIOHTTPOpenW(unescaped, compression);
02629         else
02630 #endif
02631             context = xmlOutputCallbackTable[i].opencallback(unescaped);
02632         if (context != NULL)
02633             break;
02634         }
02635     }
02636     xmlFree(unescaped);
02637     }
02638 
02639     /*
02640      * If this failed try with a non-escaped URI this may be a strange
02641      * filename
02642      */
02643     if (context == NULL) {
02644 #ifdef HAVE_ZLIB_H
02645     if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) {
02646         context = xmlGzfileOpenW(URI, compression);
02647         if (context != NULL) {
02648         ret = xmlAllocOutputBufferInternal(encoder);
02649         if (ret != NULL) {
02650             ret->context = context;
02651             ret->writecallback = xmlGzfileWrite;
02652             ret->closecallback = xmlGzfileClose;
02653         }
02654         return(ret);
02655         }
02656     }
02657 #endif
02658     for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
02659         if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
02660         (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
02661 #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H)
02662         /*  Need to pass compression parameter into HTTP open calls  */
02663         if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch)
02664             context = xmlIOHTTPOpenW(URI, compression);
02665         else
02666 #endif
02667             context = xmlOutputCallbackTable[i].opencallback(URI);
02668         if (context != NULL)
02669             break;
02670         }
02671     }
02672     }
02673 
02674     if (context == NULL) {
02675     return(NULL);
02676     }
02677 
02678     /*
02679      * Allocate the Output buffer front-end.
02680      */
02681     ret = xmlAllocOutputBufferInternal(encoder);
02682     if (ret != NULL) {
02683     ret->context = context;
02684     ret->writecallback = xmlOutputCallbackTable[i].writecallback;
02685     ret->closecallback = xmlOutputCallbackTable[i].closecallback;
02686     }
02687     return(ret);
02688 }
02689 
02705 xmlOutputBufferPtr
02706 xmlOutputBufferCreateFilename(const char *URI,
02707                               xmlCharEncodingHandlerPtr encoder,
02708                               int compression ATTRIBUTE_UNUSED) {
02709     if ((xmlOutputBufferCreateFilenameValue)) {
02710         return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
02711     }
02712     return __xmlOutputBufferCreateFilename(URI, encoder, compression);
02713 }
02714 #endif /* LIBXML_OUTPUT_ENABLED */
02715 
02726 xmlParserInputBufferPtr
02727 xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
02728     xmlParserInputBufferPtr ret;
02729 
02730     if (xmlInputCallbackInitialized == 0)
02731     xmlRegisterDefaultInputCallbacks();
02732 
02733     if (file == NULL) return(NULL);
02734 
02735     ret = xmlAllocParserInputBuffer(enc);
02736     if (ret != NULL) {
02737         ret->context = file;
02738     ret->readcallback = xmlFileRead;
02739     ret->closecallback = xmlFileFlush;
02740     }
02741 
02742     return(ret);
02743 }
02744 
02745 #ifdef LIBXML_OUTPUT_ENABLED
02746 
02756 xmlOutputBufferPtr
02757 xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
02758     xmlOutputBufferPtr ret;
02759 
02760     if (xmlOutputCallbackInitialized == 0)
02761     xmlRegisterDefaultOutputCallbacks();
02762 
02763     if (file == NULL) return(NULL);
02764 
02765     ret = xmlAllocOutputBufferInternal(encoder);
02766     if (ret != NULL) {
02767         ret->context = file;
02768     ret->writecallback = xmlFileWrite;
02769     ret->closecallback = xmlFileFlush;
02770     }
02771 
02772     return(ret);
02773 }
02774 
02784 xmlOutputBufferPtr
02785 xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
02786                             xmlCharEncodingHandlerPtr encoder) {
02787     xmlOutputBufferPtr ret;
02788 
02789     if (buffer == NULL) return(NULL);
02790 
02791     ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback)
02792                                   xmlBufferWrite,
02793                                   (xmlOutputCloseCallback)
02794                                   NULL, (void *) buffer, encoder);
02795 
02796     return(ret);
02797 }
02798 
02799 #endif /* LIBXML_OUTPUT_ENABLED */
02800 
02811 xmlParserInputBufferPtr
02812 xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
02813     xmlParserInputBufferPtr ret;
02814 
02815     if (fd < 0) return(NULL);
02816 
02817     ret = xmlAllocParserInputBuffer(enc);
02818     if (ret != NULL) {
02819         ret->context = (void *) (long) fd;
02820     ret->readcallback = xmlFdRead;
02821     ret->closecallback = xmlFdClose;
02822     }
02823 
02824     return(ret);
02825 }
02826 
02838 xmlParserInputBufferPtr
02839 xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
02840     xmlParserInputBufferPtr ret;
02841     int errcode;
02842 
02843     if (size <= 0) return(NULL);
02844     if (mem == NULL) return(NULL);
02845 
02846     ret = xmlAllocParserInputBuffer(enc);
02847     if (ret != NULL) {
02848         ret->context = (void *) mem;
02849     ret->readcallback = (xmlInputReadCallback) xmlNop;
02850     ret->closecallback = NULL;
02851     errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
02852     if (errcode != 0) {
02853         xmlFree(ret);
02854         return(NULL);
02855     }
02856     }
02857 
02858     return(ret);
02859 }
02860 
02874 xmlParserInputBufferPtr
02875 xmlParserInputBufferCreateStatic(const char *mem, int size,
02876                                  xmlCharEncoding enc) {
02877     xmlParserInputBufferPtr ret;
02878 
02879     if (size <= 0) return(NULL);
02880     if (mem == NULL) return(NULL);
02881 
02882     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
02883     if (ret == NULL) {
02884     xmlIOErrMemory("creating input buffer");
02885     return(NULL);
02886     }
02887     memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
02888     ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size);
02889     if (ret->buffer == NULL) {
02890         xmlFree(ret);
02891     return(NULL);
02892     }
02893     ret->encoder = xmlGetCharEncodingHandler(enc);
02894     if (ret->encoder != NULL)
02895         ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
02896     else
02897         ret->raw = NULL;
02898     ret->compressed = -1;
02899     ret->context = (void *) mem;
02900     ret->readcallback = NULL;
02901     ret->closecallback = NULL;
02902 
02903     return(ret);
02904 }
02905 
02906 #ifdef LIBXML_OUTPUT_ENABLED
02907 
02917 xmlOutputBufferPtr
02918 xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
02919     xmlOutputBufferPtr ret;
02920 
02921     if (fd < 0) return(NULL);
02922 
02923     ret = xmlAllocOutputBufferInternal(encoder);
02924     if (ret != NULL) {
02925         ret->context = (void *) (long) fd;
02926     ret->writecallback = xmlFdWrite;
02927     ret->closecallback = NULL;
02928     }
02929 
02930     return(ret);
02931 }
02932 #endif /* LIBXML_OUTPUT_ENABLED */
02933 
02946 xmlParserInputBufferPtr
02947 xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
02948      xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
02949     xmlParserInputBufferPtr ret;
02950 
02951     if (ioread == NULL) return(NULL);
02952 
02953     ret = xmlAllocParserInputBuffer(enc);
02954     if (ret != NULL) {
02955         ret->context = (void *) ioctx;
02956     ret->readcallback = ioread;
02957     ret->closecallback = ioclose;
02958     }
02959 
02960     return(ret);
02961 }
02962 
02963 #ifdef LIBXML_OUTPUT_ENABLED
02964 
02976 xmlOutputBufferPtr
02977 xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
02978      xmlOutputCloseCallback  ioclose, void *ioctx,
02979      xmlCharEncodingHandlerPtr encoder) {
02980     xmlOutputBufferPtr ret;
02981 
02982     if (iowrite == NULL) return(NULL);
02983 
02984     ret = xmlAllocOutputBufferInternal(encoder);
02985     if (ret != NULL) {
02986         ret->context = (void *) ioctx;
02987     ret->writecallback = iowrite;
02988     ret->closecallback = ioclose;
02989     }
02990 
02991     return(ret);
02992 }
02993 #endif /* LIBXML_OUTPUT_ENABLED */
02994 
03003 xmlParserInputBufferCreateFilenameFunc
03004 xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
03005 {
03006     xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue;
03007     if (old == NULL) {
03008         old = __xmlParserInputBufferCreateFilename;
03009     }
03010 
03011     xmlParserInputBufferCreateFilenameValue = func;
03012     return(old);
03013 }
03014 
03023 xmlOutputBufferCreateFilenameFunc
03024 xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
03025 {
03026     xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
03027 #ifdef LIBXML_OUTPUT_ENABLED
03028     if (old == NULL) {
03029         old = __xmlOutputBufferCreateFilename;
03030     }
03031 #endif
03032     xmlOutputBufferCreateFilenameValue = func;
03033     return(old);
03034 }
03035 
03049 int
03050 xmlParserInputBufferPush(xmlParserInputBufferPtr in,
03051                      int len, const char *buf) {
03052     int nbchars = 0;
03053     int ret;
03054 
03055     if (len < 0) return(0);
03056     if ((in == NULL) || (in->error)) return(-1);
03057     if (in->encoder != NULL) {
03058         unsigned int use;
03059 
03060         /*
03061      * Store the data in the incoming raw buffer
03062      */
03063         if (in->raw == NULL) {
03064         in->raw = xmlBufferCreate();
03065     }
03066     ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
03067     if (ret != 0)
03068         return(-1);
03069 
03070     /*
03071      * convert as much as possible to the parser reading buffer.
03072      */
03073     use = in->raw->use;
03074     nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
03075     if (nbchars < 0) {
03076         xmlIOErr(XML_IO_ENCODER, NULL);
03077         in->error = XML_IO_ENCODER;
03078         return(-1);
03079     }
03080     in->rawconsumed += (use - in->raw->use);
03081     } else {
03082     nbchars = len;
03083         ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
03084     if (ret != 0)
03085         return(-1);
03086     }
03087 #ifdef DEBUG_INPUT
03088     xmlGenericError(xmlGenericErrorContext,
03089         "I/O: pushed %d chars, buffer %d/%d\n",
03090             nbchars, in->buffer->use, in->buffer->size);
03091 #endif
03092     return(nbchars);
03093 }
03094 
03101 static int
03102 endOfInput (void * context ATTRIBUTE_UNUSED,
03103         char * buffer ATTRIBUTE_UNUSED,
03104         int len ATTRIBUTE_UNUSED) {
03105     return(0);
03106 }
03107 
03123 int
03124 xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
03125     char *buffer = NULL;
03126     int res = 0;
03127     int nbchars = 0;
03128     int buffree;
03129     unsigned int needSize;
03130 
03131     if ((in == NULL) || (in->error)) return(-1);
03132     if ((len <= MINLEN) && (len != 4))
03133         len = MINLEN;
03134 
03135     buffree = in->buffer->size - in->buffer->use;
03136     if (buffree <= 0) {
03137     xmlIOErr(XML_IO_BUFFER_FULL, NULL);
03138     in->error = XML_IO_BUFFER_FULL;
03139     return(-1);
03140     }
03141 
03142     needSize = in->buffer->use + len + 1;
03143     if (needSize > in->buffer->size){
03144         if (!xmlBufferResize(in->buffer, needSize)){
03145         xmlIOErrMemory("growing input buffer");
03146         in->error = XML_ERR_NO_MEMORY;
03147             return(-1);
03148         }
03149     }
03150     buffer = (char *)&in->buffer->content[in->buffer->use];
03151 
03152     /*
03153      * Call the read method for this I/O type.
03154      */
03155     if (in->readcallback != NULL) {
03156     res = in->readcallback(in->context, &buffer[0], len);
03157     if (res <= 0)
03158         in->readcallback = endOfInput;
03159     } else {
03160     xmlIOErr(XML_IO_NO_INPUT, NULL);
03161     in->error = XML_IO_NO_INPUT;
03162     return(-1);
03163     }
03164     if (res < 0) {
03165     return(-1);
03166     }
03167     len = res;
03168     if (in->encoder != NULL) {
03169         unsigned int use;
03170 
03171         /*
03172      * Store the data in the incoming raw buffer
03173      */
03174         if (in->raw == NULL) {
03175         in->raw = xmlBufferCreate();
03176     }
03177     res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
03178     if (res != 0)
03179         return(-1);
03180 
03181     /*
03182      * convert as much as possible to the parser reading buffer.
03183      */
03184     use = in->raw->use;
03185     nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
03186     if (nbchars < 0) {
03187         xmlIOErr(XML_IO_ENCODER, NULL);
03188         in->error = XML_IO_ENCODER;
03189         return(-1);
03190     }
03191     in->rawconsumed += (use - in->raw->use);
03192     } else {
03193     nbchars = len;
03194     in->buffer->use += nbchars;
03195     buffer[nbchars] = 0;
03196     }
03197 #ifdef DEBUG_INPUT
03198     xmlGenericError(xmlGenericErrorContext,
03199         "I/O: read %d chars, buffer %d/%d\n",
03200             nbchars, in->buffer->use, in->buffer->size);
03201 #endif
03202     return(nbchars);
03203 }
03204 
03217 int
03218 xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
03219     if ((in == NULL) || (in->error)) return(-1);
03220     if (in->readcallback != NULL)
03221     return(xmlParserInputBufferGrow(in, len));
03222     else if ((in->buffer != NULL) &&
03223              (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE))
03224     return(0);
03225     else
03226         return(-1);
03227 }
03228 
03229 #ifdef LIBXML_OUTPUT_ENABLED
03230 
03244 int
03245 xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
03246     int nbchars = 0; /* number of chars to output to I/O */
03247     int ret;         /* return from function call */
03248     int written = 0; /* number of char written to I/O so far */
03249     int chunk;       /* number of byte curreent processed from buf */
03250 
03251     if ((out == NULL) || (out->error)) return(-1);
03252     if (len < 0) return(0);
03253     if (out->error) return(-1);
03254 
03255     do {
03256     chunk = len;
03257     if (chunk > 4 * MINLEN)
03258         chunk = 4 * MINLEN;
03259 
03260     /*
03261      * first handle encoding stuff.
03262      */
03263     if (out->encoder != NULL) {
03264         /*
03265          * Store the data in the incoming raw buffer
03266          */
03267         if (out->conv == NULL) {
03268         out->conv = xmlBufferCreate();
03269         }
03270         ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
03271         if (ret != 0)
03272             return(-1);
03273 
03274         if ((out->buffer->use < MINLEN) && (chunk == len))
03275         goto done;
03276 
03277         /*
03278          * convert as much as possible to the parser reading buffer.
03279          */
03280         ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
03281         if ((ret < 0) && (ret != -3)) {
03282         xmlIOErr(XML_IO_ENCODER, NULL);
03283         out->error = XML_IO_ENCODER;
03284         return(-1);
03285         }
03286         nbchars = out->conv->use;
03287     } else {
03288         ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk);
03289         if (ret != 0)
03290             return(-1);
03291         nbchars = out->buffer->use;
03292     }
03293     buf += chunk;
03294     len -= chunk;
03295 
03296     if ((nbchars < MINLEN) && (len <= 0))
03297         goto done;
03298 
03299     if (out->writecallback) {
03300         /*
03301          * second write the stuff to the I/O channel
03302          */
03303         if (out->encoder != NULL) {
03304         ret = out->writecallback(out->context,
03305                  (const char *)out->conv->content, nbchars);
03306         if (ret >= 0)
03307             xmlBufferShrink(out->conv, ret);
03308         } else {
03309         ret = out->writecallback(out->context,
03310                  (const char *)out->buffer->content, nbchars);
03311         if (ret >= 0)
03312             xmlBufferShrink(out->buffer, ret);
03313         }
03314         if (ret < 0) {
03315         xmlIOErr(XML_IO_WRITE, NULL);
03316         out->error = XML_IO_WRITE;
03317         return(ret);
03318         }
03319         out->written += ret;
03320     }
03321     written += nbchars;
03322     } while (len > 0);
03323 
03324 done:
03325 #ifdef DEBUG_INPUT
03326     xmlGenericError(xmlGenericErrorContext,
03327         "I/O: wrote %d chars\n", written);
03328 #endif
03329     return(written);
03330 }
03331 
03345 static int
03346 xmlEscapeContent(unsigned char* out, int *outlen,
03347                  const xmlChar* in, int *inlen) {
03348     unsigned char* outstart = out;
03349     const unsigned char* base = in;
03350     unsigned char* outend = out + *outlen;
03351     const unsigned char* inend;
03352 
03353     inend = in + (*inlen);
03354 
03355     while ((in < inend) && (out < outend)) {
03356     if (*in == '<') {
03357         if (outend - out < 4) break;
03358         *out++ = '&';
03359         *out++ = 'l';
03360         *out++ = 't';
03361         *out++ = ';';
03362     } else if (*in == '>') {
03363         if (outend - out < 4) break;
03364         *out++ = '&';
03365         *out++ = 'g';
03366         *out++ = 't';
03367         *out++ = ';';
03368     } else if (*in == '&') {
03369         if (outend - out < 5) break;
03370         *out++ = '&';
03371         *out++ = 'a';
03372         *out++ = 'm';
03373         *out++ = 'p';
03374         *out++ = ';';
03375     } else if (*in == '\r') {
03376         if (outend - out < 5) break;
03377         *out++ = '&';
03378         *out++ = '#';
03379         *out++ = '1';
03380         *out++ = '3';
03381         *out++ = ';';
03382     } else {
03383         *out++ = (unsigned char) *in;
03384     }
03385     ++in;
03386     }
03387     *outlen = out - outstart;
03388     *inlen = in - base;
03389     return(0);
03390 }
03391 
03407 int
03408 xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
03409                            xmlCharEncodingOutputFunc escaping) {
03410     int nbchars = 0; /* number of chars to output to I/O */
03411     int ret;         /* return from function call */
03412     int written = 0; /* number of char written to I/O so far */
03413     int oldwritten=0;/* loop guard */
03414     int chunk;       /* number of byte currently processed from str */
03415     int len;         /* number of bytes in str */
03416     int cons;        /* byte from str consumed */
03417 
03418     if ((out == NULL) || (out->error) || (str == NULL) ||
03419         (out->buffer == NULL) ||
03420     (out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1);
03421     len = strlen((const char *)str);
03422     if (len < 0) return(0);
03423     if (out->error) return(-1);
03424     if (escaping == NULL) escaping = xmlEscapeContent;
03425 
03426     do {
03427         oldwritten = written;
03428 
03429         /*
03430      * how many bytes to consume and how many bytes to store.
03431      */
03432     cons = len;
03433     chunk = (out->buffer->size - out->buffer->use) - 1;
03434 
03435         /*
03436      * make sure we have enough room to save first, if this is
03437      * not the case force a flush, but make sure we stay in the loop
03438      */
03439     if (chunk < 40) {
03440         if (xmlBufferGrow(out->buffer, out->buffer->size + 100) < 0)
03441             return(-1);
03442             oldwritten = -1;
03443         continue;
03444     }
03445 
03446     /*
03447      * first handle encoding stuff.
03448      */
03449     if (out->encoder != NULL) {
03450         /*
03451          * Store the data in the incoming raw buffer
03452          */
03453         if (out->conv == NULL) {
03454         out->conv = xmlBufferCreate();
03455         }
03456         ret = escaping(out->buffer->content + out->buffer->use ,
03457                        &chunk, str, &cons);
03458         if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
03459             return(-1);
03460         out->buffer->use += chunk;
03461         out->buffer->content[out->buffer->use] = 0;
03462 
03463         if ((out->buffer->use < MINLEN) && (cons == len))
03464         goto done;
03465 
03466         /*
03467          * convert as much as possible to the output buffer.
03468          */
03469         ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
03470         if ((ret < 0) && (ret != -3)) {
03471         xmlIOErr(XML_IO_ENCODER, NULL);
03472         out->error = XML_IO_ENCODER;
03473         return(-1);
03474         }
03475         nbchars = out->conv->use;
03476     } else {
03477         ret = escaping(out->buffer->content + out->buffer->use ,
03478                        &chunk, str, &cons);
03479         if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
03480             return(-1);
03481         out->buffer->use += chunk;
03482         out->buffer->content[out->buffer->use] = 0;
03483         nbchars = out->buffer->use;
03484     }
03485     str += cons;
03486     len -= cons;
03487 
03488     if ((nbchars < MINLEN) && (len <= 0))
03489         goto done;
03490 
03491     if (out->writecallback) {
03492         /*
03493          * second write the stuff to the I/O channel
03494          */
03495         if (out->encoder != NULL) {
03496         ret = out->writecallback(out->context,
03497                  (const char *)out->conv->content, nbchars);
03498         if (ret >= 0)
03499             xmlBufferShrink(out->conv, ret);
03500         } else {
03501         ret = out->writecallback(out->context,
03502                  (const char *)out->buffer->content, nbchars);
03503         if (ret >= 0)
03504             xmlBufferShrink(out->buffer, ret);
03505         }
03506         if (ret < 0) {
03507         xmlIOErr(XML_IO_WRITE, NULL);
03508         out->error = XML_IO_WRITE;
03509         return(ret);
03510         }
03511         out->written += ret;
03512     } else if (out->buffer->size - out->buffer->use < MINLEN) {
03513         xmlBufferResize(out->buffer, out->buffer->size + MINLEN);
03514     }
03515     written += nbchars;
03516     } while ((len > 0) && (oldwritten != written));
03517 
03518 done:
03519 #ifdef DEBUG_INPUT
03520     xmlGenericError(xmlGenericErrorContext,
03521         "I/O: wrote %d chars\n", written);
03522 #endif
03523     return(written);
03524 }
03525 
03539 int
03540 xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
03541     int len;
03542 
03543     if ((out == NULL) || (out->error)) return(-1);
03544     if (str == NULL)
03545         return(-1);
03546     len = strlen(str);
03547 
03548     if (len > 0)
03549     return(xmlOutputBufferWrite(out, len, str));
03550     return(len);
03551 }
03552 
03561 int
03562 xmlOutputBufferFlush(xmlOutputBufferPtr out) {
03563     int nbchars = 0, ret = 0;
03564 
03565     if ((out == NULL) || (out->error)) return(-1);
03566     /*
03567      * first handle encoding stuff.
03568      */
03569     if ((out->conv != NULL) && (out->encoder != NULL)) {
03570     /*
03571      * convert as much as possible to the parser reading buffer.
03572      */
03573     nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
03574     if (nbchars < 0) {
03575         xmlIOErr(XML_IO_ENCODER, NULL);
03576         out->error = XML_IO_ENCODER;
03577         return(-1);
03578     }
03579     }
03580 
03581     /*
03582      * second flush the stuff to the I/O channel
03583      */
03584     if ((out->conv != NULL) && (out->encoder != NULL) &&
03585     (out->writecallback != NULL)) {
03586     ret = out->writecallback(out->context,
03587                (const char *)out->conv->content, out->conv->use);
03588     if (ret >= 0)
03589         xmlBufferShrink(out->conv, ret);
03590     } else if (out->writecallback != NULL) {
03591     ret = out->writecallback(out->context,
03592                (const char *)out->buffer->content, out->buffer->use);
03593     if (ret >= 0)
03594         xmlBufferShrink(out->buffer, ret);
03595     }
03596     if (ret < 0) {
03597     xmlIOErr(XML_IO_FLUSH, NULL);
03598     out->error = XML_IO_FLUSH;
03599     return(ret);
03600     }
03601     out->written += ret;
03602 
03603 #ifdef DEBUG_INPUT
03604     xmlGenericError(xmlGenericErrorContext,
03605         "I/O: flushed %d chars\n", ret);
03606 #endif
03607     return(ret);
03608 }
03609 #endif /* LIBXML_OUTPUT_ENABLED */
03610 
03619 char *
03620 xmlParserGetDirectory(const char *filename) {
03621     char *ret = NULL;
03622     char dir[1024];
03623     char *cur;
03624 
03625 #ifdef _WIN32_WCE  /* easy way by now ... wince does not have dirs! */
03626     return NULL;
03627 #endif
03628 
03629     if (xmlInputCallbackInitialized == 0)
03630     xmlRegisterDefaultInputCallbacks();
03631 
03632     if (filename == NULL) return(NULL);
03633 
03634 #if defined(WIN32) && !defined(__CYGWIN__)
03635 #   define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
03636 #else
03637 #   define IS_XMLPGD_SEP(ch) (ch=='/')
03638 #endif
03639 
03640     strncpy(dir, filename, 1023);
03641     dir[1023] = 0;
03642     cur = &dir[strlen(dir)];
03643     while (cur > dir) {
03644          if (IS_XMLPGD_SEP(*cur)) break;
03645      cur --;
03646     }
03647     if (IS_XMLPGD_SEP(*cur)) {
03648         if (cur == dir) dir[1] = 0;
03649     else *cur = 0;
03650     ret = xmlMemStrdup(dir);
03651     } else {
03652         if (getcwd(dir, 1024) != NULL) {
03653         dir[1023] = 0;
03654         ret = xmlMemStrdup(dir);
03655     }
03656     }
03657     return(ret);
03658 #undef IS_XMLPGD_SEP
03659 }
03660 
03661 /****************************************************************
03662  *                              *
03663  *      External entities loading           *
03664  *                              *
03665  ****************************************************************/
03666 
03679 xmlParserInputPtr
03680 xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
03681 #ifdef LIBXML_HTTP_ENABLED
03682     if ((ret != NULL) && (ret->buf != NULL) &&
03683         (ret->buf->readcallback == xmlIOHTTPRead) &&
03684         (ret->buf->context != NULL)) {
03685         const char *encoding;
03686         const char *redir;
03687         const char *mime;
03688         int code;
03689 
03690         code = xmlNanoHTTPReturnCode(ret->buf->context);
03691         if (code >= 400) {
03692             /* fatal error */
03693         if (ret->filename != NULL)
03694         __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
03695                          (const char *) ret->filename);
03696         else
03697         __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
03698             xmlFreeInputStream(ret);
03699             ret = NULL;
03700         } else {
03701 
03702             mime = xmlNanoHTTPMimeType(ret->buf->context);
03703             if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
03704                 (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
03705                 encoding = xmlNanoHTTPEncoding(ret->buf->context);
03706                 if (encoding != NULL) {
03707                     xmlCharEncodingHandlerPtr handler;
03708 
03709                     handler = xmlFindCharEncodingHandler(encoding);
03710                     if (handler != NULL) {
03711                         xmlSwitchInputEncoding(ctxt, ret, handler);
03712                     } else {
03713                         __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
03714                                          "Unknown encoding %s",
03715                                          BAD_CAST encoding, NULL);
03716                     }
03717                     if (ret->encoding == NULL)
03718                         ret->encoding = xmlStrdup(BAD_CAST encoding);
03719                 }
03720 #if 0
03721             } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
03722 #endif
03723             }
03724             redir = xmlNanoHTTPRedir(ret->buf->context);
03725             if (redir != NULL) {
03726                 if (ret->filename != NULL)
03727                     xmlFree((xmlChar *) ret->filename);
03728                 if (ret->directory != NULL) {
03729                     xmlFree((xmlChar *) ret->directory);
03730                     ret->directory = NULL;
03731                 }
03732                 ret->filename =
03733                     (char *) xmlStrdup((const xmlChar *) redir);
03734             }
03735         }
03736     }
03737 #endif
03738     return(ret);
03739 }
03740 
03741 static int xmlNoNetExists(const char *URL) {
03742     const char *path;
03743 
03744     if (URL == NULL)
03745     return(0);
03746 
03747     if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17))
03748 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
03749     path = &URL[17];
03750 #else
03751     path = &URL[16];
03752 #endif
03753     else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) {
03754 #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
03755     path = &URL[8];
03756 #else
03757     path = &URL[7];
03758 #endif
03759     } else
03760     path = URL;
03761 
03762     return xmlCheckFilename(path);
03763 }
03764 
03765 #ifdef LIBXML_CATALOG_ENABLED
03766 
03779 static xmlChar *
03780 xmlResolveResourceFromCatalog(const char *URL, const char *ID,
03781                               xmlParserCtxtPtr ctxt) {
03782     xmlChar *resource = NULL;
03783     xmlCatalogAllow pref;
03784 
03785     /*
03786      * If the resource doesn't exists as a file,
03787      * try to load it from the resource pointed in the catalogs
03788      */
03789     pref = xmlCatalogGetDefaults();
03790 
03791     if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) {
03792     /*
03793      * Do a local lookup
03794      */
03795     if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
03796         ((pref == XML_CATA_ALLOW_ALL) ||
03797          (pref == XML_CATA_ALLOW_DOCUMENT))) {
03798         resource = xmlCatalogLocalResolve(ctxt->catalogs,
03799                           (const xmlChar *)ID,
03800                           (const xmlChar *)URL);
03801         }
03802     /*
03803      * Try a global lookup
03804      */
03805     if ((resource == NULL) &&
03806         ((pref == XML_CATA_ALLOW_ALL) ||
03807          (pref == XML_CATA_ALLOW_GLOBAL))) {
03808         resource = xmlCatalogResolve((const xmlChar *)ID,
03809                      (const xmlChar *)URL);
03810     }
03811     if ((resource == NULL) && (URL != NULL))
03812         resource = xmlStrdup((const xmlChar *) URL);
03813 
03814     /*
03815      * TODO: do an URI lookup on the reference
03816      */
03817     if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) {
03818         xmlChar *tmp = NULL;
03819 
03820         if ((ctxt != NULL) && (ctxt->catalogs != NULL) &&
03821         ((pref == XML_CATA_ALLOW_ALL) ||
03822          (pref == XML_CATA_ALLOW_DOCUMENT))) {
03823         tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
03824         }
03825         if ((tmp == NULL) &&
03826         ((pref == XML_CATA_ALLOW_ALL) ||
03827              (pref == XML_CATA_ALLOW_GLOBAL))) {
03828         tmp = xmlCatalogResolveURI(resource);
03829         }
03830 
03831         if (tmp != NULL) {
03832         xmlFree(resource);
03833         resource = tmp;
03834         }
03835     }
03836     }
03837 
03838     return resource;
03839 }
03840 
03841 #endif
03842 
03853 static xmlParserInputPtr
03854 xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
03855                                xmlParserCtxtPtr ctxt)
03856 {
03857     xmlParserInputPtr ret = NULL;
03858     xmlChar *resource = NULL;
03859 
03860 #ifdef DEBUG_EXTERNAL_ENTITIES
03861     xmlGenericError(xmlGenericErrorContext,
03862                     "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
03863 #endif
03864     if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
03865         int options = ctxt->options;
03866 
03867     ctxt->options -= XML_PARSE_NONET;
03868         ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
03869     ctxt->options = options;
03870     return(ret);
03871     }
03872 #ifdef LIBXML_CATALOG_ENABLED
03873     resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
03874 #endif
03875 
03876     if (resource == NULL)
03877         resource = (xmlChar *) URL;
03878 
03879     if (resource == NULL) {
03880         if (ID == NULL)
03881             ID = "NULL";
03882         __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
03883         return (NULL);
03884     }
03885     ret = xmlNewInputFromFile(ctxt, (const char *) resource);
03886     if ((resource != NULL) && (resource != (xmlChar *) URL))
03887         xmlFree(resource);
03888     return (ret);
03889 }
03890 
03891 static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
03892        xmlDefaultExternalEntityLoader;
03893 
03900 void
03901 xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
03902     xmlCurrentExternalEntityLoader = f;
03903 }
03904 
03912 xmlExternalEntityLoader
03913 xmlGetExternalEntityLoader(void) {
03914     return(xmlCurrentExternalEntityLoader);
03915 }
03916 
03928 xmlParserInputPtr
03929 xmlLoadExternalEntity(const char *URL, const char *ID,
03930                       xmlParserCtxtPtr ctxt) {
03931     if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
03932     char *canonicFilename;
03933     xmlParserInputPtr ret;
03934 
03935     canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
03936     if (canonicFilename == NULL) {
03937             xmlIOErrMemory("building canonical path\n");
03938         return(NULL);
03939     }
03940 
03941     ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
03942     xmlFree(canonicFilename);
03943     return(ret);
03944     }
03945     return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
03946 }
03947 
03948 /************************************************************************
03949  *                                  *
03950  *      Disabling Network access                *
03951  *                                  *
03952  ************************************************************************/
03953 
03965 xmlParserInputPtr
03966 xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
03967                              xmlParserCtxtPtr ctxt) {
03968     xmlParserInputPtr input = NULL;
03969     xmlChar *resource = NULL;
03970 
03971 #ifdef LIBXML_CATALOG_ENABLED
03972     resource = xmlResolveResourceFromCatalog(URL, ID, ctxt);
03973 #endif
03974 
03975     if (resource == NULL)
03976     resource = (xmlChar *) URL;
03977 
03978     if (resource != NULL) {
03979         if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
03980             (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
03981             xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource);
03982         if (resource != (xmlChar *) URL)
03983         xmlFree(resource);
03984         return(NULL);
03985     }
03986     }
03987     input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt);
03988     if (resource != (xmlChar *) URL)
03989     xmlFree(resource);
03990     return(input);
03991 }
03992 
03993 #define bottom_xmlIO
03994 #include "elfgcchack.h"

Generated on Sun May 27 2012 04:34:46 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.