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