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