DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
/* * xmlIO.c : implementation of the I/O interfaces used by the parser * * See Copyright for the status of this software. * * daniel@veillard.com * * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char */ #define IN_LIBXML #include "libxml.h" #include
#ifdef HAVE_ERRNO_H #include
#endif #ifdef HAVE_SYS_TYPES_H #include
#endif #ifdef HAVE_SYS_STAT_H #include
#endif #ifdef HAVE_FCNTL_H #include
#endif #ifdef HAVE_UNISTD_H #include
#endif #ifdef HAVE_STDLIB_H #include
#endif #ifdef HAVE_ZLIB_H #include
#endif #ifdef WIN32 #include
#endif /* Figure a portable way to know if a file is a directory. */ #ifndef HAVE_STAT # ifdef HAVE__STAT /* MS C library seems to define stat and _stat. The definition is identical. Still, mapping them to each other causes a warning. */ # ifndef _MSC_VER # define stat(x,y) _stat(x,y) # endif # define HAVE_STAT # endif #endif #ifdef HAVE_STAT # ifndef S_ISDIR # ifdef _S_ISDIR # define S_ISDIR(x) _S_ISDIR(x) # else # ifdef S_IFDIR # ifndef S_IFMT # ifdef _S_IFMT # define S_IFMT _S_IFMT # endif # endif # ifdef S_IFMT # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # endif # endif # endif # endif #endif #include
#include
#include
#include
#include
#include
#include
#include
#ifdef LIBXML_CATALOG_ENABLED #include
#endif #include
/* #define VERBOSE_FAILURE */ /* #define DEBUG_EXTERNAL_ENTITIES */ /* #define DEBUG_INPUT */ #ifdef DEBUG_INPUT #define MINLEN 40 #else #define MINLEN 4000 #endif /* * Input I/O callback sets */ typedef struct _xmlInputCallback { xmlInputMatchCallback matchcallback; xmlInputOpenCallback opencallback; xmlInputReadCallback readcallback; xmlInputCloseCallback closecallback; } xmlInputCallback; #define MAX_INPUT_CALLBACK 15 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK]; static int xmlInputCallbackNr = 0; static int xmlInputCallbackInitialized = 0; #ifdef LIBXML_OUTPUT_ENABLED /* * Output I/O callback sets */ typedef struct _xmlOutputCallback { xmlOutputMatchCallback matchcallback; xmlOutputOpenCallback opencallback; xmlOutputWriteCallback writecallback; xmlOutputCloseCallback closecallback; } xmlOutputCallback; #define MAX_OUTPUT_CALLBACK 15 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK]; static int xmlOutputCallbackNr = 0; static int xmlOutputCallbackInitialized = 0; #endif /* LIBXML_OUTPUT_ENABLED */ /************************************************************************ * * * Tree memory error handler * * * ************************************************************************/ static const char *IOerr[] = { "Unknown IO error", /* UNKNOWN */ "Permission denied", /* EACCES */ "Resource temporarily unavailable",/* EAGAIN */ "Bad file descriptor", /* EBADF */ "Bad message", /* EBADMSG */ "Resource busy", /* EBUSY */ "Operation canceled", /* ECANCELED */ "No child processes", /* ECHILD */ "Resource deadlock avoided",/* EDEADLK */ "Domain error", /* EDOM */ "File exists", /* EEXIST */ "Bad address", /* EFAULT */ "File too large", /* EFBIG */ "Operation in progress", /* EINPROGRESS */ "Interrupted function call",/* EINTR */ "Invalid argument", /* EINVAL */ "Input/output error", /* EIO */ "Is a directory", /* EISDIR */ "Too many open files", /* EMFILE */ "Too many links", /* EMLINK */ "Inappropriate message buffer length",/* EMSGSIZE */ "Filename too long", /* ENAMETOOLONG */ "Too many open files in system",/* ENFILE */ "No such device", /* ENODEV */ "No such file or directory",/* ENOENT */ "Exec format error", /* ENOEXEC */ "No locks available", /* ENOLCK */ "Not enough space", /* ENOMEM */ "No space left on device", /* ENOSPC */ "Function not implemented", /* ENOSYS */ "Not a directory", /* ENOTDIR */ "Directory not empty", /* ENOTEMPTY */ "Not supported", /* ENOTSUP */ "Inappropriate I/O control operation",/* ENOTTY */ "No such device or address",/* ENXIO */ "Operation not permitted", /* EPERM */ "Broken pipe", /* EPIPE */ "Result too large", /* ERANGE */ "Read-only file system", /* EROFS */ "Invalid seek", /* ESPIPE */ "No such process", /* ESRCH */ "Operation timed out", /* ETIMEDOUT */ "Improper link", /* EXDEV */ "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */ "encoder error", /* XML_IO_ENCODER */ "flush error", "write error", "no input", "buffer full", "loading error", "not a socket", /* ENOTSOCK */ "already connected", /* EISCONN */ "connection refused", /* ECONNREFUSED */ "unreachable network", /* ENETUNREACH */ "adddress in use", /* EADDRINUSE */ "already in use", /* EALREADY */ "unknown address familly", /* EAFNOSUPPORT */ }; #if defined(WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) /** * __xmlIOWin32UTF8ToWChar: * @u8String: uft-8 string * * Convert a string from utf-8 to wchar (WINDOWS ONLY!) */ static wchar_t * __xmlIOWin32UTF8ToWChar(const char *u8String) { wchar_t *wString = NULL; if (u8String) { int wLen = MultiByteToWideChar(CP_UTF8,0,u8String,-1,NULL,0); if (wLen) { wString = malloc((wLen+1) * sizeof(wchar_t)); if (wString) { if (MultiByteToWideChar(CP_UTF8,0,u8String,-1,wString,wLen+1) == 0) { free(wString); wString = NULL; } } } } return wString; } #endif /** * xmlIOErrMemory: * @extra: extra informations * * Handle an out of memory condition */ static void xmlIOErrMemory(const char *extra) { __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra); } /** * __xmlIOErr: * @code: the error number * @ * @extra: extra informations * * Handle an I/O error */ void __xmlIOErr(int domain, int code, const char *extra) { unsigned int idx; if (code == 0) { #ifdef HAVE_ERRNO_H if (errno == 0) code = 0; #ifdef EACCES else if (errno == EACCES) code = XML_IO_EACCES; #endif #ifdef EAGAIN else if (errno == EAGAIN) code = XML_IO_EAGAIN; #endif #ifdef EBADF else if (errno == EBADF) code = XML_IO_EBADF; #endif #ifdef EBADMSG else if (errno == EBADMSG) code = XML_IO_EBADMSG; #endif #ifdef EBUSY else if (errno == EBUSY) code = XML_IO_EBUSY; #endif #ifdef ECANCELED else if (errno == ECANCELED) code = XML_IO_ECANCELED; #endif #ifdef ECHILD else if (errno == ECHILD) code = XML_IO_ECHILD; #endif #ifdef EDEADLK else if (errno == EDEADLK) code = XML_IO_EDEADLK; #endif #ifdef EDOM else if (errno == EDOM) code = XML_IO_EDOM; #endif #ifdef EEXIST else if (errno == EEXIST) code = XML_IO_EEXIST; #endif #ifdef EFAULT else if (errno == EFAULT) code = XML_IO_EFAULT; #endif #ifdef EFBIG else if (errno == EFBIG) code = XML_IO_EFBIG; #endif #ifdef EINPROGRESS else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS; #endif #ifdef EINTR else if (errno == EINTR) code = XML_IO_EINTR; #endif #ifdef EINVAL else if (errno == EINVAL) code = XML_IO_EINVAL; #endif #ifdef EIO else if (errno == EIO) code = XML_IO_EIO; #endif #ifdef EISDIR else if (errno == EISDIR) code = XML_IO_EISDIR; #endif #ifdef EMFILE else if (errno == EMFILE) code = XML_IO_EMFILE; #endif #ifdef EMLINK else if (errno == EMLINK) code = XML_IO_EMLINK; #endif #ifdef EMSGSIZE else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE; #endif #ifdef ENAMETOOLONG else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG; #endif #ifdef ENFILE else if (errno == ENFILE) code = XML_IO_ENFILE; #endif #ifdef ENODEV else if (errno == ENODEV) code = XML_IO_ENODEV; #endif #ifdef ENOENT else if (errno == ENOENT) code = XML_IO_ENOENT; #endif #ifdef ENOEXEC else if (errno == ENOEXEC) code = XML_IO_ENOEXEC; #endif #ifdef ENOLCK else if (errno == ENOLCK) code = XML_IO_ENOLCK; #endif #ifdef ENOMEM else if (errno == ENOMEM) code = XML_IO_ENOMEM; #endif #ifdef ENOSPC else if (errno == ENOSPC) code = XML_IO_ENOSPC; #endif #ifdef ENOSYS else if (errno == ENOSYS) code = XML_IO_ENOSYS; #endif #ifdef ENOTDIR else if (errno == ENOTDIR) code = XML_IO_ENOTDIR; #endif #ifdef ENOTEMPTY else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY; #endif #ifdef ENOTSUP else if (errno == ENOTSUP) code = XML_IO_ENOTSUP; #endif #ifdef ENOTTY else if (errno == ENOTTY) code = XML_IO_ENOTTY; #endif #ifdef ENXIO else if (errno == ENXIO) code = XML_IO_ENXIO; #endif #ifdef EPERM else if (errno == EPERM) code = XML_IO_EPERM; #endif #ifdef EPIPE else if (errno == EPIPE) code = XML_IO_EPIPE; #endif #ifdef ERANGE else if (errno == ERANGE) code = XML_IO_ERANGE; #endif #ifdef EROFS else if (errno == EROFS) code = XML_IO_EROFS; #endif #ifdef ESPIPE else if (errno == ESPIPE) code = XML_IO_ESPIPE; #endif #ifdef ESRCH else if (errno == ESRCH) code = XML_IO_ESRCH; #endif #ifdef ETIMEDOUT else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT; #endif #ifdef EXDEV else if (errno == EXDEV) code = XML_IO_EXDEV; #endif #ifdef ENOTSOCK else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK; #endif #ifdef EISCONN else if (errno == EISCONN) code = XML_IO_EISCONN; #endif #ifdef ECONNREFUSED else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED; #endif #ifdef ETIMEDOUT else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT; #endif #ifdef ENETUNREACH else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH; #endif #ifdef EADDRINUSE else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE; #endif #ifdef EINPROGRESS else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS; #endif #ifdef EALREADY else if (errno == EALREADY) code = XML_IO_EALREADY; #endif #ifdef EAFNOSUPPORT else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT; #endif else code = XML_IO_UNKNOWN; #endif /* HAVE_ERRNO_H */ } idx = 0; if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN; if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0; __xmlSimpleError(domain, code, NULL, IOerr[idx], extra); } /** * xmlIOErr: * @code: the error number * @extra: extra informations * * Handle an I/O error */ static void xmlIOErr(int code, const char *extra) { __xmlIOErr(XML_FROM_IO, code, extra); } /** * __xmlLoaderErr: * @ctx: the parser context * @extra: extra informations * * Handle a resource access error */ void __xmlLoaderErr(void *ctx, const char *msg, const char *filename) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlStructuredErrorFunc schannel = NULL; xmlGenericErrorFunc channel = NULL; void *data = NULL; xmlErrorLevel level = XML_ERR_ERROR; if ((ctxt != NULL) && (ctxt->disableSAX != 0) && (ctxt->instate == XML_PARSER_EOF)) return; if ((ctxt != NULL) && (ctxt->sax != NULL)) { if (ctxt->validate) { channel = ctxt->sax->error; level = XML_ERR_ERROR; } else { channel = ctxt->sax->warning; level = XML_ERR_WARNING; } if (ctxt->sax->initialized == XML_SAX2_MAGIC) schannel = ctxt->sax->serror; data = ctxt->userData; } __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO, XML_IO_LOAD_ERROR, level, NULL, 0, filename, NULL, NULL, 0, 0, msg, filename); } /************************************************************************ * * * Tree memory error handler * * * ************************************************************************/ /** * xmlNormalizeWindowsPath: * @path: the input file path * * This function is obsolete. Please see xmlURIFromPath in uri.c for * a better solution. * * Returns a canonicalized version of the path */ xmlChar * xmlNormalizeWindowsPath(const xmlChar *path) { return xmlCanonicPath(path); } /** * xmlCleanupInputCallbacks: * * clears the entire input callback table. this includes the * compiled-in I/O. */ void xmlCleanupInputCallbacks(void) { int i; if (!xmlInputCallbackInitialized) return; for (i = xmlInputCallbackNr - 1; i >= 0; i--) { xmlInputCallbackTable[i].matchcallback = NULL; xmlInputCallbackTable[i].opencallback = NULL; xmlInputCallbackTable[i].readcallback = NULL; xmlInputCallbackTable[i].closecallback = NULL; } xmlInputCallbackNr = 0; xmlInputCallbackInitialized = 0; } /** * xmlPopInputCallbacks: * * Clear the top input callback from the input stack. this includes the * compiled-in I/O. * * Returns the number of input callback registered or -1 in case of error. */ int xmlPopInputCallbacks(void) { if (!xmlInputCallbackInitialized) return(-1); if (xmlInputCallbackNr <= 0) return(-1); xmlInputCallbackNr--; xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL; xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL; xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL; xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL; return(xmlInputCallbackNr); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlCleanupOutputCallbacks: * * clears the entire output callback table. this includes the * compiled-in I/O callbacks. */ void xmlCleanupOutputCallbacks(void) { int i; if (!xmlOutputCallbackInitialized) return; for (i = xmlOutputCallbackNr - 1; i >= 0; i--) { xmlOutputCallbackTable[i].matchcallback = NULL; xmlOutputCallbackTable[i].opencallback = NULL; xmlOutputCallbackTable[i].writecallback = NULL; xmlOutputCallbackTable[i].closecallback = NULL; } xmlOutputCallbackNr = 0; xmlOutputCallbackInitialized = 0; } #endif /* LIBXML_OUTPUT_ENABLED */ /************************************************************************ * * * Standard I/O for file accesses * * * ************************************************************************/ /** * xmlCheckFilename: * @path: the path to check * * function checks to see if @path is a valid source * (file, socket...) for XML. * * if stat is not available on the target machine, * returns 1. if stat fails, returns 0 (if calling * stat on the filename fails, it can't be right). * if stat succeeds and the file is a directory, * returns 2. otherwise returns 1. */ int xmlCheckFilename (const char *path) { #ifdef HAVE_STAT struct stat stat_buffer; #endif if (path == NULL) return(0); #if defined(WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) { int retval = 0; wchar_t *wPath = __xmlIOWin32UTF8ToWChar(path); if (wPath) { struct _stat stat_buffer; if (_wstat(wPath,&stat_buffer) == 0) { retval = 1; if (((stat_buffer.st_mode & S_IFDIR) == S_IFDIR)) retval = 2; } free(wPath); } return retval; } #else #ifdef HAVE_STAT if (stat(path, &stat_buffer) == -1) return 0; #ifdef S_ISDIR if (S_ISDIR(stat_buffer.st_mode)) return 2; #endif /* S_ISDIR */ #endif /* HAVE_STAT */ #endif /* WIN32 */ return 1; } static int xmlNop(void) { return(0); } /** * xmlFdRead: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to read * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes written */ static int xmlFdRead (void * context, char * buffer, int len) { int ret; ret = read((int) (long) context, &buffer[0], len); if (ret < 0) xmlIOErr(0, "read()"); return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlFdWrite: * @context: the I/O context * @buffer: where to get data * @len: number of bytes to write * * Write @len bytes from @buffer to the I/O channel. * * Returns the number of bytes written */ static int xmlFdWrite (void * context, const char * buffer, int len) { int ret = 0; if (len > 0) { ret = write((int) (long) context, &buffer[0], len); if (ret < 0) xmlIOErr(0, "write()"); } return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlFdClose: * @context: the I/O context * * Close an I/O channel * * Returns 0 in case of success and error code otherwise */ static int xmlFdClose (void * context) { int ret; ret = close((int) (long) context); if (ret < 0) xmlIOErr(0, "close()"); return(ret); } /** * xmlFileMatch: * @filename: the URI for matching * * input from FILE * * * Returns 1 if matches, 0 otherwise */ int xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) { return(1); } /** * xmlFileOpen_real: * @filename: the URI for matching * * input from FILE *, supports compressed input * if @filename is " " then the standard input is used * * Returns an I/O context or NULL in case of error */ static void * xmlFileOpen_real (const char *filename) { const char *path = NULL; FILE *fd; if (filename == NULL) return(NULL); if (!strcmp(filename, "-")) { fd = stdin; return((void *) fd); } if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[17]; #else path = &filename[16]; #endif else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[8]; #else path = &filename[7]; #endif } else path = filename; if (path == NULL) return(NULL); if (!xmlCheckFilename(path)) return(NULL); #if defined(WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) { wchar_t *wPath = __xmlIOWin32UTF8ToWChar(path); if (wPath) { fd = _wfopen(wPath, L"rb"); free(wPath); } else { fd = fopen(path, "rb"); } } #else fd = fopen(path, "r"); #endif /* WIN32 */ if (fd == NULL) xmlIOErr(0, path); return((void *) fd); } /** * xmlFileOpen: * @filename: the URI for matching * * Wrapper around xmlFileOpen_real that try it with an unescaped * version of @filename, if this fails fallback to @filename * * Returns a handler or NULL in case or failure */ void * xmlFileOpen (const char *filename) { char *unescaped; void *retval; unescaped = xmlURIUnescapeString(filename, 0, NULL); if (unescaped != NULL) { retval = xmlFileOpen_real(unescaped); xmlFree(unescaped); } else { retval = xmlFileOpen_real(filename); } return retval; } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlFileOpenW: * @filename: the URI for matching * * output to from FILE *, * if @filename is "-" then the standard output is used * * Returns an I/O context or NULL in case of error */ static void * xmlFileOpenW (const char *filename) { const char *path = NULL; FILE *fd; if (!strcmp(filename, "-")) { fd = stdout; return((void *) fd); } if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[17]; #else path = &filename[16]; #endif else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[8]; #else path = &filename[7]; #endif } else path = filename; if (path == NULL) return(NULL); #if defined(WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) { wchar_t *wPath = __xmlIOWin32UTF8ToWChar(path); if (wPath) { fd = _wfopen(wPath, L"wb"); free(wPath); } else { fd = fopen(path, "wb"); } } #else fd = fopen(path, "wb"); #endif /* WIN32 */ if (fd == NULL) xmlIOErr(0, path); return((void *) fd); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlFileRead: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes written or < 0 in case of failure */ int xmlFileRead (void * context, char * buffer, int len) { int ret; if ((context == NULL) || (buffer == NULL)) return(-1); ret = fread(&buffer[0], 1, len, (FILE *) context); if (ret < 0) xmlIOErr(0, "fread()"); return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlFileWrite: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Write @len bytes from @buffer to the I/O channel. * * Returns the number of bytes written */ static int xmlFileWrite (void * context, const char * buffer, int len) { int items; if ((context == NULL) || (buffer == NULL)) return(-1); items = fwrite(&buffer[0], len, 1, (FILE *) context); if ((items == 0) && (ferror((FILE *) context))) { xmlIOErr(0, "fwrite()"); return(-1); } return(items * len); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlFileClose: * @context: the I/O context * * Close an I/O channel * * Returns 0 or -1 in case of error */ int xmlFileClose (void * context) { FILE *fil; int ret; if (context == NULL) return(-1); fil = (FILE *) context; if ((fil == stdout) || (fil == stderr)) { ret = fflush(fil); if (ret < 0) xmlIOErr(0, "fflush()"); return(0); } if (fil == stdin) return(0); ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0; if (ret < 0) xmlIOErr(0, "fclose()"); return(ret); } /** * xmlFileFlush: * @context: the I/O context * * Flush an I/O channel */ static int xmlFileFlush (void * context) { int ret; if (context == NULL) return(-1); ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0; if (ret < 0) xmlIOErr(0, "fflush()"); return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlBufferWrite: * @context: the xmlBuffer * @buffer: the data to write * @len: number of bytes to write * * Write @len bytes from @buffer to the xml buffer * * Returns the number of bytes written */ static int xmlBufferWrite (void * context, const char * buffer, int len) { int ret; ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len); if (ret != 0) return(-1); return(len); } #endif #ifdef HAVE_ZLIB_H /************************************************************************ * * * I/O for compressed file accesses * * * ************************************************************************/ /** * xmlGzfileMatch: * @filename: the URI for matching * * input from compressed file test * * Returns 1 if matches, 0 otherwise */ static int xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) { return(1); } /** * xmlGzfileOpen_real: * @filename: the URI for matching * * input from compressed file open * if @filename is " " then the standard input is used * * Returns an I/O context or NULL in case of error */ static void * xmlGzfileOpen_real (const char *filename) { const char *path = NULL; gzFile fd; if (!strcmp(filename, "-")) { fd = gzdopen(dup(0), "rb"); return((void *) fd); } if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[17]; #else path = &filename[16]; #endif else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[8]; #else path = &filename[7]; #endif } else path = filename; if (path == NULL) return(NULL); if (!xmlCheckFilename(path)) return(NULL); fd = gzopen(path, "rb"); return((void *) fd); } /** * xmlGzfileOpen: * @filename: the URI for matching * * Wrapper around xmlGzfileOpen if the open fais, it will * try to unescape @filename */ static void * xmlGzfileOpen (const char *filename) { char *unescaped; void *retval; retval = xmlGzfileOpen_real(filename); if (retval == NULL) { unescaped = xmlURIUnescapeString(filename, 0, NULL); if (unescaped != NULL) { retval = xmlGzfileOpen_real(unescaped); } xmlFree(unescaped); } return retval; } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlGzfileOpenW: * @filename: the URI for matching * @compression: the compression factor (0 - 9 included) * * input from compressed file open * if @filename is " " then the standard input is used * * Returns an I/O context or NULL in case of error */ static void * xmlGzfileOpenW (const char *filename, int compression) { const char *path = NULL; char mode[15]; gzFile fd; snprintf(mode, sizeof(mode), "wb%d", compression); if (!strcmp(filename, "-")) { fd = gzdopen(dup(1), mode); return((void *) fd); } if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[17]; #else path = &filename[16]; #endif else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &filename[8]; #else path = &filename[7]; #endif } else path = filename; if (path == NULL) return(NULL); fd = gzopen(path, mode); return((void *) fd); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlGzfileRead: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Read @len bytes to @buffer from the compressed I/O channel. * * Returns the number of bytes written */ static int xmlGzfileRead (void * context, char * buffer, int len) { int ret; ret = gzread((gzFile) context, &buffer[0], len); if (ret < 0) xmlIOErr(0, "gzread()"); return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlGzfileWrite: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Write @len bytes from @buffer to the compressed I/O channel. * * Returns the number of bytes written */ static int xmlGzfileWrite (void * context, const char * buffer, int len) { int ret; ret = gzwrite((gzFile) context, (char *) &buffer[0], len); if (ret < 0) xmlIOErr(0, "gzwrite()"); return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlGzfileClose: * @context: the I/O context * * Close a compressed I/O channel */ static int xmlGzfileClose (void * context) { int ret; ret = (gzclose((gzFile) context) == Z_OK ) ? 0 : -1; if (ret < 0) xmlIOErr(0, "gzclose()"); return(ret); } #endif /* HAVE_ZLIB_H */ #ifdef LIBXML_HTTP_ENABLED /************************************************************************ * * * I/O for HTTP file accesses * * * ************************************************************************/ #ifdef LIBXML_OUTPUT_ENABLED typedef struct xmlIOHTTPWriteCtxt_ { int compression; char * uri; void * doc_buff; } xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr; #ifdef HAVE_ZLIB_H #define DFLT_WBITS ( -15 ) #define DFLT_MEM_LVL ( 8 ) #define GZ_MAGIC1 ( 0x1f ) #define GZ_MAGIC2 ( 0x8b ) #define LXML_ZLIB_OS_CODE ( 0x03 ) #define INIT_HTTP_BUFF_SIZE ( 32768 ) #define DFLT_ZLIB_RATIO ( 5 ) /* ** Data structure and functions to work with sending compressed data ** via HTTP. */ typedef struct xmlZMemBuff_ { unsigned long size; unsigned long crc; unsigned char * zbuff; z_stream zctrl; } xmlZMemBuff, *xmlZMemBuffPtr; /** * append_reverse_ulong * @buff: Compressed memory buffer * @data: Unsigned long to append * * Append a unsigned long in reverse byte order to the end of the * memory buffer. */ static void append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) { int idx; if ( buff == NULL ) return; /* ** This is plagiarized from putLong in gzio.c (zlib source) where ** the number "4" is hardcoded. If zlib is ever patched to ** support 64 bit file sizes, this code would need to be patched ** as well. */ for ( idx = 0; idx < 4; idx++ ) { *buff->zctrl.next_out = ( data & 0xff ); data >>= 8; buff->zctrl.next_out++; } return; } /** * * xmlFreeZMemBuff * @buff: The memory buffer context to clear * * Release all the resources associated with the compressed memory buffer. */ static void xmlFreeZMemBuff( xmlZMemBuffPtr buff ) { #ifdef DEBUG_HTTP int z_err; #endif if ( buff == NULL ) return; xmlFree( buff->zbuff ); #ifdef DEBUG_HTTP z_err = deflateEnd( &buff->zctrl ); if ( z_err != Z_OK ) xmlGenericError( xmlGenericErrorContext, "xmlFreeZMemBuff: Error releasing zlib context: %d\n", z_err ); #else deflateEnd( &buff->zctrl ); #endif xmlFree( buff ); return; } /** * xmlCreateZMemBuff *@compression: Compression value to use * * Create a memory buffer to hold the compressed XML document. The * compressed document in memory will end up being identical to what * would be created if gzopen/gzwrite/gzclose were being used to * write the document to disk. The code for the header/trailer data to * the compression is plagiarized from the zlib source files. */ static void * xmlCreateZMemBuff( int compression ) { int z_err; int hdr_lgth; xmlZMemBuffPtr buff = NULL; if ( ( compression < 1 ) || ( compression > 9 ) ) return ( NULL ); /* Create the control and data areas */ buff = xmlMalloc( sizeof( xmlZMemBuff ) ); if ( buff == NULL ) { xmlIOErrMemory("creating buffer context"); return ( NULL ); } (void)memset( buff, 0, sizeof( xmlZMemBuff ) ); buff->size = INIT_HTTP_BUFF_SIZE; buff->zbuff = xmlMalloc( buff->size ); if ( buff->zbuff == NULL ) { xmlFreeZMemBuff( buff ); xmlIOErrMemory("creating buffer"); return ( NULL ); } z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED, DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY ); if ( z_err != Z_OK ) { xmlChar msg[500]; xmlFreeZMemBuff( buff ); buff = NULL; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlCreateZMemBuff: %s %d\n", "Error initializing compression context. ZLIB error:", z_err ); xmlIOErr(XML_IO_WRITE, (const char *) msg); return ( NULL ); } /* Set the header data. The CRC will be needed for the trailer */ buff->crc = crc32( 0L, NULL, 0 ); hdr_lgth = snprintf( (char *)buff->zbuff, buff->size, "%c%c%c%c%c%c%c%c%c%c", GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE ); buff->zctrl.next_out = buff->zbuff + hdr_lgth; buff->zctrl.avail_out = buff->size - hdr_lgth; return ( buff ); } /** * xmlZMemBuffExtend * @buff: Buffer used to compress and consolidate data. * @ext_amt: Number of bytes to extend the buffer. * * Extend the internal buffer used to store the compressed data by the * specified amount. * * Returns 0 on success or -1 on failure to extend the buffer. On failure * the original buffer still exists at the original size. */ static int xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) { int rc = -1; size_t new_size; size_t cur_used; unsigned char * tmp_ptr = NULL; if ( buff == NULL ) return ( -1 ); else if ( ext_amt == 0 ) return ( 0 ); cur_used = buff->zctrl.next_out - buff->zbuff; new_size = buff->size + ext_amt; #ifdef DEBUG_HTTP if ( cur_used > new_size ) xmlGenericError( xmlGenericErrorContext, "xmlZMemBuffExtend: %s\n%s %d bytes.\n", "Buffer overwrite detected during compressed memory", "buffer extension. Overflowed by", (cur_used - new_size ) ); #endif tmp_ptr = xmlRealloc( buff->zbuff, new_size ); if ( tmp_ptr != NULL ) { rc = 0; buff->size = new_size; buff->zbuff = tmp_ptr; buff->zctrl.next_out = tmp_ptr + cur_used; buff->zctrl.avail_out = new_size - cur_used; } else { xmlChar msg[500]; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlZMemBuffExtend: %s %lu bytes.\n", "Allocation failure extending output buffer to", new_size ); xmlIOErr(XML_IO_WRITE, (const char *) msg); } return ( rc ); } /** * xmlZMemBuffAppend * @buff: Buffer used to compress and consolidate data * @src: Uncompressed source content to append to buffer * @len: Length of source data to append to buffer * * Compress and append data to the internal buffer. The data buffer * will be expanded if needed to store the additional data. * * Returns the number of bytes appended to the buffer or -1 on error. */ static int xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) { int z_err; size_t min_accept; if ( ( buff == NULL ) || ( src == NULL ) ) return ( -1 ); buff->zctrl.avail_in = len; buff->zctrl.next_in = (unsigned char *)src; while ( buff->zctrl.avail_in > 0 ) { /* ** Extend the buffer prior to deflate call if a reasonable amount ** of output buffer space is not available. */ min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO; if ( buff->zctrl.avail_out <= min_accept ) { if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) return ( -1 ); } z_err = deflate( &buff->zctrl, Z_NO_FLUSH ); if ( z_err != Z_OK ) { xmlChar msg[500]; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlZMemBuffAppend: %s %d %s - %d", "Compression error while appending", len, "bytes to buffer. ZLIB error", z_err ); xmlIOErr(XML_IO_WRITE, (const char *) msg); return ( -1 ); } } buff->crc = crc32( buff->crc, (unsigned char *)src, len ); return ( len ); } /** * xmlZMemBuffGetContent * @buff: Compressed memory content buffer * @data_ref: Pointer reference to point to compressed content * * Flushes the compression buffers, appends gzip file trailers and * returns the compressed content and length of the compressed data. * NOTE: The gzip trailer code here is plagiarized from zlib source. * * Returns the length of the compressed data or -1 on error. */ static int xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) { int zlgth = -1; int z_err; if ( ( buff == NULL ) || ( data_ref == NULL ) ) return ( -1 ); /* Need to loop until compression output buffers are flushed */ do { z_err = deflate( &buff->zctrl, Z_FINISH ); if ( z_err == Z_OK ) { /* In this case Z_OK means more buffer space needed */ if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) return ( -1 ); } } while ( z_err == Z_OK ); /* If the compression state is not Z_STREAM_END, some error occurred */ if ( z_err == Z_STREAM_END ) { /* Need to append the gzip data trailer */ if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) { if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 ) return ( -1 ); } /* ** For whatever reason, the CRC and length data are pushed out ** in reverse byte order. So a memcpy can't be used here. */ append_reverse_ulong( buff, buff->crc ); append_reverse_ulong( buff, buff->zctrl.total_in ); zlgth = buff->zctrl.next_out - buff->zbuff; *data_ref = (char *)buff->zbuff; } else { xmlChar msg[500]; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlZMemBuffGetContent: %s - %d\n", "Error flushing zlib buffers. Error code", z_err ); xmlIOErr(XML_IO_WRITE, (const char *) msg); } return ( zlgth ); } #endif /* LIBXML_OUTPUT_ENABLED */ #endif /* HAVE_ZLIB_H */ #ifdef LIBXML_OUTPUT_ENABLED /** * xmlFreeHTTPWriteCtxt * @ctxt: Context to cleanup * * Free allocated memory and reclaim system resources. * * No return value. */ static void xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt ) { if ( ctxt->uri != NULL ) xmlFree( ctxt->uri ); if ( ctxt->doc_buff != NULL ) { #ifdef HAVE_ZLIB_H if ( ctxt->compression > 0 ) { xmlFreeZMemBuff( ctxt->doc_buff ); } else #endif { xmlOutputBufferClose( ctxt->doc_buff ); } } xmlFree( ctxt ); return; } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlIOHTTPMatch: * @filename: the URI for matching * * check if the URI matches an HTTP one * * Returns 1 if matches, 0 otherwise */ int xmlIOHTTPMatch (const char *filename) { if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7)) return(1); return(0); } /** * xmlIOHTTPOpen: * @filename: the URI for matching * * open an HTTP I/O channel * * Returns an I/O context or NULL in case of error */ void * xmlIOHTTPOpen (const char *filename) { return(xmlNanoHTTPOpen(filename, NULL)); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlIOHTTPOpenW: * @post_uri: The destination URI for the document * @compression: The compression desired for the document. * * Open a temporary buffer to collect the document for a subsequent HTTP POST * request. Non-static as is called from the output buffer creation routine. * * Returns an I/O context or NULL in case of error. */ void * xmlIOHTTPOpenW(const char *post_uri, int compression) { xmlIOHTTPWriteCtxtPtr ctxt = NULL; if (post_uri == NULL) return (NULL); ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt)); if (ctxt == NULL) { xmlIOErrMemory("creating HTTP output context"); return (NULL); } (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt)); ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri); if (ctxt->uri == NULL) { xmlIOErrMemory("copying URI"); xmlFreeHTTPWriteCtxt(ctxt); return (NULL); } /* * ** Since the document length is required for an HTTP post, * ** need to put the document into a buffer. A memory buffer * ** is being used to avoid pushing the data to disk and back. */ #ifdef HAVE_ZLIB_H if ((compression > 0) && (compression <= 9)) { ctxt->compression = compression; ctxt->doc_buff = xmlCreateZMemBuff(compression); } else #endif { /* Any character conversions should have been done before this */ ctxt->doc_buff = xmlAllocOutputBuffer(NULL); } if (ctxt->doc_buff == NULL) { xmlFreeHTTPWriteCtxt(ctxt); ctxt = NULL; } return (ctxt); } #endif /* LIBXML_OUTPUT_ENABLED */ #ifdef LIBXML_OUTPUT_ENABLED /** * xmlIOHTTPDfltOpenW * @post_uri: The destination URI for this document. * * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent * HTTP post command. This function should generally not be used as * the open callback is short circuited in xmlOutputBufferCreateFile. * * Returns a pointer to the new IO context. */ static void * xmlIOHTTPDfltOpenW( const char * post_uri ) { return ( xmlIOHTTPOpenW( post_uri, 0 ) ); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlIOHTTPRead: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes written */ int xmlIOHTTPRead(void * context, char * buffer, int len) { if ((buffer == NULL) || (len < 0)) return(-1); return(xmlNanoHTTPRead(context, &buffer[0], len)); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlIOHTTPWrite * @context: previously opened writing context * @buffer: data to output to temporary buffer * @len: bytes to output * * Collect data from memory buffer into a temporary file for later * processing. * * Returns number of bytes written. */ static int xmlIOHTTPWrite( void * context, const char * buffer, int len ) { xmlIOHTTPWriteCtxtPtr ctxt = context; if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) ) return ( -1 ); if ( len > 0 ) { /* Use gzwrite or fwrite as previously setup in the open call */ #ifdef HAVE_ZLIB_H if ( ctxt->compression > 0 ) len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len ); else #endif len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer ); if ( len < 0 ) { xmlChar msg[500]; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlIOHTTPWrite: %s\n%s '%s'.\n", "Error appending to internal buffer.", "Error sending document to URI", ctxt->uri ); xmlIOErr(XML_IO_WRITE, (const char *) msg); } } return ( len ); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlIOHTTPClose: * @context: the I/O context * * Close an HTTP I/O channel * * Returns 0 */ int xmlIOHTTPClose (void * context) { xmlNanoHTTPClose(context); return 0; } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlIOHTTCloseWrite * @context: The I/O context * @http_mthd: The HTTP method to be used when sending the data * * Close the transmit HTTP I/O channel and actually send the data. */ static int xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) { int close_rc = -1; int http_rtn = 0; int content_lgth = 0; xmlIOHTTPWriteCtxtPtr ctxt = context; char * http_content = NULL; char * content_encoding = NULL; char * content_type = (char *) "text/xml"; void * http_ctxt = NULL; if ( ( ctxt == NULL ) || ( http_mthd == NULL ) ) return ( -1 ); /* Retrieve the content from the appropriate buffer */ #ifdef HAVE_ZLIB_H if ( ctxt->compression > 0 ) { content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content ); content_encoding = (char *) "Content-Encoding: gzip"; } else #endif { /* Pull the data out of the memory output buffer */ xmlOutputBufferPtr dctxt = ctxt->doc_buff; http_content = (char *)dctxt->buffer->content; content_lgth = dctxt->buffer->use; } if ( http_content == NULL ) { xmlChar msg[500]; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n", "Error retrieving content.\nUnable to", http_mthd, "data to URI", ctxt->uri ); xmlIOErr(XML_IO_WRITE, (const char *) msg); } else { http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content, &content_type, content_encoding, content_lgth ); if ( http_ctxt != NULL ) { #ifdef DEBUG_HTTP /* If testing/debugging - dump reply with request content */ FILE * tst_file = NULL; char buffer[ 4096 ]; char * dump_name = NULL; int avail; xmlGenericError( xmlGenericErrorContext, "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n", http_mthd, ctxt->uri, xmlNanoHTTPReturnCode( http_ctxt ) ); /* ** Since either content or reply may be gzipped, ** dump them to separate files instead of the ** standard error context. */ dump_name = tempnam( NULL, "lxml" ); if ( dump_name != NULL ) { (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name ); tst_file = fopen( buffer, "wb" ); if ( tst_file != NULL ) { xmlGenericError( xmlGenericErrorContext, "Transmitted content saved in file: %s\n", buffer ); fwrite( http_content, sizeof( char ), content_lgth, tst_file ); fclose( tst_file ); } (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name ); tst_file = fopen( buffer, "wb" ); if ( tst_file != NULL ) { xmlGenericError( xmlGenericErrorContext, "Reply content saved in file: %s\n", buffer ); while ( (avail = xmlNanoHTTPRead( http_ctxt, buffer, sizeof( buffer ) )) > 0 ) { fwrite( buffer, sizeof( char ), avail, tst_file ); } fclose( tst_file ); } free( dump_name ); } #endif /* DEBUG_HTTP */ http_rtn = xmlNanoHTTPReturnCode( http_ctxt ); if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) ) close_rc = 0; else { xmlChar msg[500]; xmlStrPrintf(msg, 500, (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n", http_mthd, content_lgth, "bytes to URI", ctxt->uri, "failed. HTTP return code:", http_rtn ); xmlIOErr(XML_IO_WRITE, (const char *) msg); } xmlNanoHTTPClose( http_ctxt ); xmlFree( content_type ); } } /* Final cleanups */ xmlFreeHTTPWriteCtxt( ctxt ); return ( close_rc ); } /** * xmlIOHTTPClosePut * * @context: The I/O context * * Close the transmit HTTP I/O channel and actually send data using a PUT * HTTP method. */ static int xmlIOHTTPClosePut( void * ctxt ) { return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) ); } /** * xmlIOHTTPClosePost * * @context: The I/O context * * Close the transmit HTTP I/O channel and actually send data using a POST * HTTP method. */ static int xmlIOHTTPClosePost( void * ctxt ) { return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) ); } #endif /* LIBXML_OUTPUT_ENABLED */ #endif /* LIBXML_HTTP_ENABLED */ #ifdef LIBXML_FTP_ENABLED /************************************************************************ * * * I/O for FTP file accesses * * * ************************************************************************/ /** * xmlIOFTPMatch: * @filename: the URI for matching * * check if the URI matches an FTP one * * Returns 1 if matches, 0 otherwise */ int xmlIOFTPMatch (const char *filename) { if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6)) return(1); return(0); } /** * xmlIOFTPOpen: * @filename: the URI for matching * * open an FTP I/O channel * * Returns an I/O context or NULL in case of error */ void * xmlIOFTPOpen (const char *filename) { return(xmlNanoFTPOpen(filename)); } /** * xmlIOFTPRead: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes written */ int xmlIOFTPRead(void * context, char * buffer, int len) { if ((buffer == NULL) || (len < 0)) return(-1); return(xmlNanoFTPRead(context, &buffer[0], len)); } /** * xmlIOFTPClose: * @context: the I/O context * * Close an FTP I/O channel * * Returns 0 */ int xmlIOFTPClose (void * context) { return ( xmlNanoFTPClose(context) ); } #endif /* LIBXML_FTP_ENABLED */ /** * xmlRegisterInputCallbacks: * @matchFunc: the xmlInputMatchCallback * @openFunc: the xmlInputOpenCallback * @readFunc: the xmlInputReadCallback * @closeFunc: the xmlInputCloseCallback * * Register a new set of I/O callback for handling parser input. * * Returns the registered handler number or -1 in case of error */ int xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc) { if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) { return(-1); } xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc; xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc; xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc; xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc; xmlInputCallbackInitialized = 1; return(xmlInputCallbackNr++); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlRegisterOutputCallbacks: * @matchFunc: the xmlOutputMatchCallback * @openFunc: the xmlOutputOpenCallback * @writeFunc: the xmlOutputWriteCallback * @closeFunc: the xmlOutputCloseCallback * * Register a new set of I/O callback for handling output. * * Returns the registered handler number or -1 in case of error */ int xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc, xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc, xmlOutputCloseCallback closeFunc) { if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) { return(-1); } xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc; xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc; xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc; xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc; xmlOutputCallbackInitialized = 1; return(xmlOutputCallbackNr++); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlRegisterDefaultInputCallbacks: * * Registers the default compiled-in I/O handlers. */ void xmlRegisterDefaultInputCallbacks (void) { if (xmlInputCallbackInitialized) return; xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen, xmlFileRead, xmlFileClose); #ifdef HAVE_ZLIB_H xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen, xmlGzfileRead, xmlGzfileClose); #endif /* HAVE_ZLIB_H */ #ifdef LIBXML_HTTP_ENABLED xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen, xmlIOHTTPRead, xmlIOHTTPClose); #endif /* LIBXML_HTTP_ENABLED */ #ifdef LIBXML_FTP_ENABLED xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, xmlIOFTPRead, xmlIOFTPClose); #endif /* LIBXML_FTP_ENABLED */ xmlInputCallbackInitialized = 1; } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlRegisterDefaultOutputCallbacks: * * Registers the default compiled-in I/O handlers. */ void xmlRegisterDefaultOutputCallbacks (void) { if (xmlOutputCallbackInitialized) return; xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW, xmlFileWrite, xmlFileClose); #ifdef LIBXML_HTTP_ENABLED xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, xmlIOHTTPWrite, xmlIOHTTPClosePut); #endif /********************************* No way a-priori to distinguish between gzipped files from uncompressed ones except opening if existing then closing and saving with same compression ratio ... a pain. #ifdef HAVE_ZLIB_H xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen, xmlGzfileWrite, xmlGzfileClose); #endif Nor FTP PUT .... #ifdef LIBXML_FTP_ENABLED xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, xmlIOFTPWrite, xmlIOFTPClose); #endif **********************************/ xmlOutputCallbackInitialized = 1; } #ifdef LIBXML_HTTP_ENABLED /** * xmlRegisterHTTPPostCallbacks: * * By default, libxml submits HTTP output requests using the "PUT" method. * Calling this method changes the HTTP output method to use the "POST" * method instead. * */ void xmlRegisterHTTPPostCallbacks( void ) { /* Register defaults if not done previously */ if ( xmlOutputCallbackInitialized == 0 ) xmlRegisterDefaultOutputCallbacks( ); xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, xmlIOHTTPWrite, xmlIOHTTPClosePost); return; } #endif #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlAllocParserInputBuffer: * @enc: the charset encoding if known * * Create a buffered parser input for progressive parsing * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlAllocParserInputBuffer(xmlCharEncoding enc) { xmlParserInputBufferPtr ret; ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer)); if (ret == NULL) { xmlIOErrMemory("creating input buffer"); return(NULL); } memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize); if (ret->buffer == NULL) { xmlFree(ret); return(NULL); } ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; ret->encoder = xmlGetCharEncodingHandler(enc); if (ret->encoder != NULL) ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); else ret->raw = NULL; ret->readcallback = NULL; ret->closecallback = NULL; ret->context = NULL; ret->compressed = -1; ret->rawconsumed = 0; return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlAllocOutputBuffer: * @encoder: the encoding converter or NULL * * Create a buffered parser output * * Returns the new parser output or NULL */ xmlOutputBufferPtr xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); if (ret == NULL) { xmlIOErrMemory("creating output buffer"); return(NULL); } memset(ret, 0, (size_t) sizeof(xmlOutputBuffer)); ret->buffer = xmlBufferCreate(); if (ret->buffer == NULL) { xmlFree(ret); return(NULL); } ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; ret->encoder = encoder; if (encoder != NULL) { ret->conv = xmlBufferCreateSize(4000); /* * This call is designed to initiate the encoder state */ xmlCharEncOutFunc(encoder, ret->conv, NULL); } else ret->conv = NULL; ret->writecallback = NULL; ret->closecallback = NULL; ret->context = NULL; ret->written = 0; return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlFreeParserInputBuffer: * @in: a buffered parser input * * Free up the memory used by a buffered parser input */ void xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) { if (in == NULL) return; if (in->raw) { xmlBufferFree(in->raw); in->raw = NULL; } if (in->encoder != NULL) { xmlCharEncCloseFunc(in->encoder); } if (in->closecallback != NULL) { in->closecallback(in->context); } if (in->buffer != NULL) { xmlBufferFree(in->buffer); in->buffer = NULL; } xmlFree(in); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlOutputBufferClose: * @out: a buffered output * * flushes and close the output I/O channel * and free up all the associated resources * * Returns the number of byte written or -1 in case of error. */ int xmlOutputBufferClose(xmlOutputBufferPtr out) { int written; int err_rc = 0; if (out == NULL) return (-1); if (out->writecallback != NULL) xmlOutputBufferFlush(out); if (out->closecallback != NULL) { err_rc = out->closecallback(out->context); } written = out->written; if (out->conv) { xmlBufferFree(out->conv); out->conv = NULL; } if (out->encoder != NULL) { xmlCharEncCloseFunc(out->encoder); } if (out->buffer != NULL) { xmlBufferFree(out->buffer); out->buffer = NULL; } if (out->error) err_rc = -1; xmlFree(out); return ((err_rc == 0) ? written : err_rc); } #endif /* LIBXML_OUTPUT_ENABLED */ xmlParserInputBufferPtr __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; int i = 0; void *context = NULL; if (xmlInputCallbackInitialized == 0) xmlRegisterDefaultInputCallbacks(); if (URI == NULL) return(NULL); /* * Try to find one of the input accept method accepting that scheme * Go in reverse to give precedence to user defined handlers. */ if (context == NULL) { for (i = xmlInputCallbackNr - 1;i >= 0;i--) { if ((xmlInputCallbackTable[i].matchcallback != NULL) && (xmlInputCallbackTable[i].matchcallback(URI) != 0)) { context = xmlInputCallbackTable[i].opencallback(URI); if (context != NULL) { break; } } } } if (context == NULL) { return(NULL); } /* * Allocate the Input buffer front-end. */ ret = xmlAllocParserInputBuffer(enc); if (ret != NULL) { ret->context = context; ret->readcallback = xmlInputCallbackTable[i].readcallback; ret->closecallback = xmlInputCallbackTable[i].closecallback; #ifdef HAVE_ZLIB_H if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) && (strcmp(URI, "-") != 0)) { if (((z_stream *)context)->avail_in > 4) { char *cptr, buff4[4]; cptr = (char *) ((z_stream *)context)->next_in; if (gzread(context, buff4, 4) == 4) { if (strncmp(buff4, cptr, 4) == 0) ret->compressed = 0; else ret->compressed = 1; gzrewind(context); } } } #endif } else xmlInputCallbackTable[i].closecallback (context); return(ret); } /** * xmlParserInputBufferCreateFilename: * @URI: a C string containing the URI or filename * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing of a file * If filename is "-' then we use stdin as the input. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. * Do an encoding check if enc == XML_CHAR_ENCODING_NONE * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { if ((xmlParserInputBufferCreateFilenameValue)) { return xmlParserInputBufferCreateFilenameValue(URI, enc); } return __xmlParserInputBufferCreateFilename(URI, enc); } #ifdef LIBXML_OUTPUT_ENABLED xmlOutputBufferPtr __xmlOutputBufferCreateFilename(const char *URI, xmlCharEncodingHandlerPtr encoder, int compression ATTRIBUTE_UNUSED) { xmlOutputBufferPtr ret; xmlURIPtr puri; int i = 0; void *context = NULL; char *unescaped = NULL; #ifdef HAVE_ZLIB_H int is_file_uri = 1; #endif if (xmlOutputCallbackInitialized == 0) xmlRegisterDefaultOutputCallbacks(); if (URI == NULL) return(NULL); puri = xmlParseURI(URI); if (puri != NULL) { #ifdef HAVE_ZLIB_H if ((puri->scheme != NULL) && (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file"))) is_file_uri = 0; #endif /* * try to limit the damages of the URI unescaping code. */ if (puri->scheme != NULL) unescaped = xmlURIUnescapeString(URI, 0, NULL); xmlFreeURI(puri); } /* * Try to find one of the output accept method accepting that scheme * Go in reverse to give precedence to user defined handlers. * try with an unescaped version of the URI */ if (unescaped != NULL) { #ifdef HAVE_ZLIB_H if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) { context = xmlGzfileOpenW(unescaped, compression); if (context != NULL) { ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = context; ret->writecallback = xmlGzfileWrite; ret->closecallback = xmlGzfileClose; } xmlFree(unescaped); return(ret); } } #endif for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { if ((xmlOutputCallbackTable[i].matchcallback != NULL) && (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) { #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H) /* Need to pass compression parameter into HTTP open calls */ if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch) context = xmlIOHTTPOpenW(unescaped, compression); else #endif context = xmlOutputCallbackTable[i].opencallback(unescaped); if (context != NULL) break; } } xmlFree(unescaped); } /* * If this failed try with a non-escaped URI this may be a strange * filename */ if (context == NULL) { #ifdef HAVE_ZLIB_H if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) { context = xmlGzfileOpenW(URI, compression); if (context != NULL) { ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = context; ret->writecallback = xmlGzfileWrite; ret->closecallback = xmlGzfileClose; } return(ret); } } #endif for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { if ((xmlOutputCallbackTable[i].matchcallback != NULL) && (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) { #if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H) /* Need to pass compression parameter into HTTP open calls */ if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch) context = xmlIOHTTPOpenW(URI, compression); else #endif context = xmlOutputCallbackTable[i].opencallback(URI); if (context != NULL) break; } } } if (context == NULL) { return(NULL); } /* * Allocate the Output buffer front-end. */ ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = context; ret->writecallback = xmlOutputCallbackTable[i].writecallback; ret->closecallback = xmlOutputCallbackTable[i].closecallback; } return(ret); } /** * xmlOutputBufferCreateFilename: * @URI: a C string containing the URI or filename * @encoder: the encoding converter or NULL * @compression: the compression ration (0 none, 9 max). * * Create a buffered output for the progressive saving of a file * If filename is "-' then we use stdout as the output. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. * TODO: currently if compression is set, the library only support * writing to a local file. * * Returns the new output or NULL */ xmlOutputBufferPtr xmlOutputBufferCreateFilename(const char *URI, xmlCharEncodingHandlerPtr encoder, int compression ATTRIBUTE_UNUSED) { if ((xmlOutputBufferCreateFilenameValue)) { return xmlOutputBufferCreateFilenameValue(URI, encoder, compression); } return __xmlOutputBufferCreateFilename(URI, encoder, compression); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlParserInputBufferCreateFile: * @file: a FILE* * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing of a FILE * * buffered C I/O * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; if (xmlInputCallbackInitialized == 0) xmlRegisterDefaultInputCallbacks(); if (file == NULL) return(NULL); ret = xmlAllocParserInputBuffer(enc); if (ret != NULL) { ret->context = file; ret->readcallback = xmlFileRead; ret->closecallback = xmlFileFlush; } return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlOutputBufferCreateFile: * @file: a FILE* * @encoder: the encoding converter or NULL * * Create a buffered output for the progressive saving to a FILE * * buffered C I/O * * Returns the new parser output or NULL */ xmlOutputBufferPtr xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; if (xmlOutputCallbackInitialized == 0) xmlRegisterDefaultOutputCallbacks(); if (file == NULL) return(NULL); ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = file; ret->writecallback = xmlFileWrite; ret->closecallback = xmlFileFlush; } return(ret); } /** * xmlOutputBufferCreateBuffer: * @buffer: a xmlBufferPtr * @encoder: the encoding converter or NULL * * Create a buffered output for the progressive saving to a xmlBuffer * * Returns the new parser output or NULL */ xmlOutputBufferPtr xmlOutputBufferCreateBuffer(xmlBufferPtr buffer, xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; if (buffer == NULL) return(NULL); ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback) xmlBufferWrite, (xmlOutputCloseCallback) NULL, (void *) buffer, encoder); return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlParserInputBufferCreateFd: * @fd: a file descriptor number * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing for the input * from a file descriptor * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; if (fd < 0) return(NULL); ret = xmlAllocParserInputBuffer(enc); if (ret != NULL) { ret->context = (void *) (long) fd; ret->readcallback = xmlFdRead; ret->closecallback = xmlFdClose; } return(ret); } /** * xmlParserInputBufferCreateMem: * @mem: the memory input * @size: the length of the memory block * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing for the input * from a memory area. * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; int errcode; if (size <= 0) return(NULL); if (mem == NULL) return(NULL); ret = xmlAllocParserInputBuffer(enc); if (ret != NULL) { ret->context = (void *) mem; ret->readcallback = (xmlInputReadCallback) xmlNop; ret->closecallback = NULL; errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size); if (errcode != 0) { xmlFree(ret); return(NULL); } } return(ret); } /** * xmlParserInputBufferCreateStatic: * @mem: the memory input * @size: the length of the memory block * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing for the input * from an immutable memory area. This will not copy the memory area to * the buffer, but the memory is expected to be available until the end of * the parsing, this is useful for example when using mmap'ed file. * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateStatic(const char *mem, int size, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; if (size <= 0) return(NULL); if (mem == NULL) return(NULL); ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer)); if (ret == NULL) { xmlIOErrMemory("creating input buffer"); return(NULL); } memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size); if (ret->buffer == NULL) { xmlFree(ret); return(NULL); } ret->encoder = xmlGetCharEncodingHandler(enc); if (ret->encoder != NULL) ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); else ret->raw = NULL; ret->compressed = -1; ret->context = (void *) mem; ret->readcallback = NULL; ret->closecallback = NULL; return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlOutputBufferCreateFd: * @fd: a file descriptor number * @encoder: the encoding converter or NULL * * Create a buffered output for the progressive saving * to a file descriptor * * Returns the new parser output or NULL */ xmlOutputBufferPtr xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; if (fd < 0) return(NULL); ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = (void *) (long) fd; ret->writecallback = xmlFdWrite; ret->closecallback = NULL; } return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlParserInputBufferCreateIO: * @ioread: an I/O read function * @ioclose: an I/O close function * @ioctx: an I/O handler * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing for the input * from an I/O handler * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; if (ioread == NULL) return(NULL); ret = xmlAllocParserInputBuffer(enc); if (ret != NULL) { ret->context = (void *) ioctx; ret->readcallback = ioread; ret->closecallback = ioclose; } return(ret); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlOutputBufferCreateIO: * @iowrite: an I/O write function * @ioclose: an I/O close function * @ioctx: an I/O handler * @encoder: the charset encoding if known * * Create a buffered output for the progressive saving * to an I/O handler * * Returns the new parser output or NULL */ xmlOutputBufferPtr xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite, xmlOutputCloseCallback ioclose, void *ioctx, xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; if (iowrite == NULL) return(NULL); ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = (void *) ioctx; ret->writecallback = iowrite; ret->closecallback = ioclose; } return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlParserInputBufferCreateFilenameDefault: * @func: function pointer to the new ParserInputBufferCreateFilenameFunc * * Registers a callback for URI input file handling * * Returns the old value of the registration function */ xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func) { xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue; if (old == NULL) { old = __xmlParserInputBufferCreateFilename; } xmlParserInputBufferCreateFilenameValue = func; return(old); } /** * xmlOutputBufferCreateFilenameDefault: * @func: function pointer to the new OutputBufferCreateFilenameFunc * * Registers a callback for URI output file handling * * Returns the old value of the registration function */ xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func) { xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue; #ifdef LIBXML_OUTPUT_ENABLED if (old == NULL) { old = __xmlOutputBufferCreateFilename; } #endif xmlOutputBufferCreateFilenameValue = func; return(old); } /** * xmlParserInputBufferPush: * @in: a buffered parser input * @len: the size in bytes of the array. * @buf: an char array * * Push the content of the arry in the input buffer * This routine handle the I18N transcoding to internal UTF-8 * This is used when operating the parser in progressive (push) mode. * * Returns the number of chars read and stored in the buffer, or -1 * in case of error. */ int xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) { int nbchars = 0; int ret; if (len < 0) return(0); if ((in == NULL) || (in->error)) return(-1); if (in->encoder != NULL) { unsigned int use; /* * Store the data in the incoming raw buffer */ if (in->raw == NULL) { in->raw = xmlBufferCreate(); } ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len); if (ret != 0) return(-1); /* * convert as much as possible to the parser reading buffer. */ use = in->raw->use; nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); if (nbchars < 0) { xmlIOErr(XML_IO_ENCODER, NULL); in->error = XML_IO_ENCODER; return(-1); } in->rawconsumed += (use - in->raw->use); } else { nbchars = len; ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars); if (ret != 0) return(-1); } #ifdef DEBUG_INPUT xmlGenericError(xmlGenericErrorContext, "I/O: pushed %d chars, buffer %d/%d\n", nbchars, in->buffer->use, in->buffer->size); #endif return(nbchars); } /** * endOfInput: * * When reading from an Input channel indicated end of file or error * don't reread from it again. */ static int endOfInput (void * context ATTRIBUTE_UNUSED, char * buffer ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) { return(0); } /** * xmlParserInputBufferGrow: * @in: a buffered parser input * @len: indicative value of the amount of chars to read * * Grow up the content of the input buffer, the old data are preserved * This routine handle the I18N transcoding to internal UTF-8 * This routine is used when operating the parser in normal (pull) mode * * TODO: one should be able to remove one extra copy by copying directly * onto in->buffer or in->raw * * Returns the number of chars read and stored in the buffer, or -1 * in case of error. */ int xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { char *buffer = NULL; int res = 0; int nbchars = 0; int buffree; unsigned int needSize; if ((in == NULL) || (in->error)) return(-1); if ((len <= MINLEN) && (len != 4)) len = MINLEN; buffree = in->buffer->size - in->buffer->use; if (buffree <= 0) { xmlIOErr(XML_IO_BUFFER_FULL, NULL); in->error = XML_IO_BUFFER_FULL; return(-1); } needSize = in->buffer->use + len + 1; if (needSize > in->buffer->size){ if (!xmlBufferResize(in->buffer, needSize)){ xmlIOErrMemory("growing input buffer"); in->error = XML_ERR_NO_MEMORY; return(-1); } } buffer = (char *)&in->buffer->content[in->buffer->use]; /* * Call the read method for this I/O type. */ if (in->readcallback != NULL) { res = in->readcallback(in->context, &buffer[0], len); if (res <= 0) in->readcallback = endOfInput; } else { xmlIOErr(XML_IO_NO_INPUT, NULL); in->error = XML_IO_NO_INPUT; return(-1); } if (res < 0) { return(-1); } len = res; if (in->encoder != NULL) { unsigned int use; /* * Store the data in the incoming raw buffer */ if (in->raw == NULL) { in->raw = xmlBufferCreate(); } res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len); if (res != 0) return(-1); /* * convert as much as possible to the parser reading buffer. */ use = in->raw->use; nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); if (nbchars < 0) { xmlIOErr(XML_IO_ENCODER, NULL); in->error = XML_IO_ENCODER; return(-1); } in->rawconsumed += (use - in->raw->use); } else { nbchars = len; in->buffer->use += nbchars; buffer[nbchars] = 0; } #ifdef DEBUG_INPUT xmlGenericError(xmlGenericErrorContext, "I/O: read %d chars, buffer %d/%d\n", nbchars, in->buffer->use, in->buffer->size); #endif return(nbchars); } /** * xmlParserInputBufferRead: * @in: a buffered parser input * @len: indicative value of the amount of chars to read * * Refresh the content of the input buffer, the old data are considered * consumed * This routine handle the I18N transcoding to internal UTF-8 * * Returns the number of chars read and stored in the buffer, or -1 * in case of error. */ int xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) { if ((in == NULL) || (in->error)) return(-1); if (in->readcallback != NULL) return(xmlParserInputBufferGrow(in, len)); else if ((in->buffer != NULL) && (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(0); else return(-1); } #ifdef LIBXML_OUTPUT_ENABLED /** * xmlOutputBufferWrite: * @out: a buffered parser output * @len: the size in bytes of the array. * @buf: an char array * * Write the content of the array in the output I/O buffer * This routine handle the I18N transcoding from internal UTF-8 * The buffer is lossless, i.e. will store in case of partial * or delayed writes. * * Returns the number of chars immediately written, or -1 * in case of error. */ int xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { int nbchars = 0; /* number of chars to output to I/O */ int ret; /* return from function call */ int written = 0; /* number of char written to I/O so far */ int chunk; /* number of byte curreent processed from buf */ if ((out == NULL) || (out->error)) return(-1); if (len < 0) return(0); if (out->error) return(-1); do { chunk = len; if (chunk > 4 * MINLEN) chunk = 4 * MINLEN; /* * first handle encoding stuff. */ if (out->encoder != NULL) { /* * Store the data in the incoming raw buffer */ if (out->conv == NULL) { out->conv = xmlBufferCreate(); } ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk); if (ret != 0) return(-1); if ((out->buffer->use < MINLEN) && (chunk == len)) goto done; /* * convert as much as possible to the parser reading buffer. */ ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); if ((ret < 0) && (ret != -3)) { xmlIOErr(XML_IO_ENCODER, NULL); out->error = XML_IO_ENCODER; return(-1); } nbchars = out->conv->use; } else { ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk); if (ret != 0) return(-1); nbchars = out->buffer->use; } buf += chunk; len -= chunk; if ((nbchars < MINLEN) && (len <= 0)) goto done; if (out->writecallback) { /* * second write the stuff to the I/O channel */ if (out->encoder != NULL) { ret = out->writecallback(out->context, (const char *)out->conv->content, nbchars); if (ret >= 0) xmlBufferShrink(out->conv, ret); } else { ret = out->writecallback(out->context, (const char *)out->buffer->content, nbchars); if (ret >= 0) xmlBufferShrink(out->buffer, ret); } if (ret < 0) { xmlIOErr(XML_IO_WRITE, NULL); out->error = XML_IO_WRITE; return(ret); } out->written += ret; } written += nbchars; } while (len > 0); done: #ifdef DEBUG_INPUT xmlGenericError(xmlGenericErrorContext, "I/O: wrote %d chars\n", written); #endif return(written); } /** * xmlEscapeContent: * @out: a pointer to an array of bytes to store the result * @outlen: the length of @out * @in: a pointer to an array of unescaped UTF-8 bytes * @inlen: the length of @in * * Take a block of UTF-8 chars in and escape them. * Returns 0 if success, or -1 otherwise * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets consumed. */ static int xmlEscapeContent(unsigned char* out, int *outlen, const xmlChar* in, int *inlen) { unsigned char* outstart = out; const unsigned char* base = in; unsigned char* outend = out + *outlen; const unsigned char* inend; inend = in + (*inlen); while ((in < inend) && (out < outend)) { if (*in == '<') { if (outend - out < 4) break; *out++ = '&'; *out++ = 'l'; *out++ = 't'; *out++ = ';'; } else if (*in == '>') { if (outend - out < 4) break; *out++ = '&'; *out++ = 'g'; *out++ = 't'; *out++ = ';'; } else if (*in == '&') { if (outend - out < 5) break; *out++ = '&'; *out++ = 'a'; *out++ = 'm'; *out++ = 'p'; *out++ = ';'; } else if (*in == '\r') { if (outend - out < 5) break; *out++ = '&'; *out++ = '#'; *out++ = '1'; *out++ = '3'; *out++ = ';'; } else { *out++ = (unsigned char) *in; } ++in; } *outlen = out - outstart; *inlen = in - base; return(0); } /** * xmlOutputBufferWriteEscape: * @out: a buffered parser output * @str: a zero terminated UTF-8 string * @escaping: an optional escaping function (or NULL) * * Write the content of the string in the output I/O buffer * This routine escapes the caracters and then handle the I18N * transcoding from internal UTF-8 * The buffer is lossless, i.e. will store in case of partial * or delayed writes. * * Returns the number of chars immediately written, or -1 * in case of error. */ int xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, xmlCharEncodingOutputFunc escaping) { int nbchars = 0; /* number of chars to output to I/O */ int ret; /* return from function call */ int written = 0; /* number of char written to I/O so far */ int oldwritten=0;/* loop guard */ int chunk; /* number of byte currently processed from str */ int len; /* number of bytes in str */ int cons; /* byte from str consumed */ if ((out == NULL) || (out->error) || (str == NULL) || (out->buffer == NULL) || (out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1); len = strlen((const char *)str); if (len < 0) return(0); if (out->error) return(-1); if (escaping == NULL) escaping = xmlEscapeContent; do { oldwritten = written; /* * how many bytes to consume and how many bytes to store. */ cons = len; chunk = (out->buffer->size - out->buffer->use) - 1; /* * first handle encoding stuff. */ if (out->encoder != NULL) { /* * Store the data in the incoming raw buffer */ if (out->conv == NULL) { out->conv = xmlBufferCreate(); } ret = escaping(out->buffer->content + out->buffer->use , &chunk, str, &cons); if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ return(-1); out->buffer->use += chunk; out->buffer->content[out->buffer->use] = 0; if ((out->buffer->use < MINLEN) && (cons == len)) goto done; /* * convert as much as possible to the output buffer. */ ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); if ((ret < 0) && (ret != -3)) { xmlIOErr(XML_IO_ENCODER, NULL); out->error = XML_IO_ENCODER; return(-1); } nbchars = out->conv->use; } else { ret = escaping(out->buffer->content + out->buffer->use , &chunk, str, &cons); if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ return(-1); out->buffer->use += chunk; out->buffer->content[out->buffer->use] = 0; nbchars = out->buffer->use; } str += cons; len -= cons; if ((nbchars < MINLEN) && (len <= 0)) goto done; if (out->writecallback) { /* * second write the stuff to the I/O channel */ if (out->encoder != NULL) { ret = out->writecallback(out->context, (const char *)out->conv->content, nbchars); if (ret >= 0) xmlBufferShrink(out->conv, ret); } else { ret = out->writecallback(out->context, (const char *)out->buffer->content, nbchars); if (ret >= 0) xmlBufferShrink(out->buffer, ret); } if (ret < 0) { xmlIOErr(XML_IO_WRITE, NULL); out->error = XML_IO_WRITE; return(ret); } out->written += ret; } else if (out->buffer->size - out->buffer->use < MINLEN) { xmlBufferResize(out->buffer, out->buffer->size + MINLEN); } written += nbchars; } while ((len > 0) && (oldwritten != written)); done: #ifdef DEBUG_INPUT xmlGenericError(xmlGenericErrorContext, "I/O: wrote %d chars\n", written); #endif return(written); } /** * xmlOutputBufferWriteString: * @out: a buffered parser output * @str: a zero terminated C string * * Write the content of the string in the output I/O buffer * This routine handle the I18N transcoding from internal UTF-8 * The buffer is lossless, i.e. will store in case of partial * or delayed writes. * * Returns the number of chars immediately written, or -1 * in case of error. */ int xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) { int len; if ((out == NULL) || (out->error)) return(-1); if (str == NULL) return(-1); len = strlen(str); if (len > 0) return(xmlOutputBufferWrite(out, len, str)); return(len); } /** * xmlOutputBufferFlush: * @out: a buffered output * * flushes the output I/O channel * * Returns the number of byte written or -1 in case of error. */ int xmlOutputBufferFlush(xmlOutputBufferPtr out) { int nbchars = 0, ret = 0; if ((out == NULL) || (out->error)) return(-1); /* * first handle encoding stuff. */ if ((out->conv != NULL) && (out->encoder != NULL)) { /* * convert as much as possible to the parser reading buffer. */ nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); if (nbchars < 0) { xmlIOErr(XML_IO_ENCODER, NULL); out->error = XML_IO_ENCODER; return(-1); } } /* * second flush the stuff to the I/O channel */ if ((out->conv != NULL) && (out->encoder != NULL) && (out->writecallback != NULL)) { ret = out->writecallback(out->context, (const char *)out->conv->content, out->conv->use); if (ret >= 0) xmlBufferShrink(out->conv, ret); } else if (out->writecallback != NULL) { ret = out->writecallback(out->context, (const char *)out->buffer->content, out->buffer->use); if (ret >= 0) xmlBufferShrink(out->buffer, ret); } if (ret < 0) { xmlIOErr(XML_IO_FLUSH, NULL); out->error = XML_IO_FLUSH; return(ret); } out->written += ret; #ifdef DEBUG_INPUT xmlGenericError(xmlGenericErrorContext, "I/O: flushed %d chars\n", ret); #endif return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlParserGetDirectory: * @filename: the path to a file * * lookup the directory for that file * * Returns a new allocated string containing the directory, or NULL. */ char * xmlParserGetDirectory(const char *filename) { char *ret = NULL; char dir[1024]; char *cur; char sep = '/'; #ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */ return NULL; #endif if (xmlInputCallbackInitialized == 0) xmlRegisterDefaultInputCallbacks(); if (filename == NULL) return(NULL); #if defined(WIN32) && !defined(__CYGWIN__) sep = '\\'; #endif strncpy(dir, filename, 1023); dir[1023] = 0; cur = &dir[strlen(dir)]; while (cur > dir) { if (*cur == sep) break; cur --; } if (*cur == sep) { if (cur == dir) dir[1] = 0; else *cur = 0; ret = xmlMemStrdup(dir); } else { if (getcwd(dir, 1024) != NULL) { dir[1023] = 0; ret = xmlMemStrdup(dir); } } return(ret); } /**************************************************************** * * * External entities loading * * * ****************************************************************/ /** * xmlCheckHTTPInput: * @ctxt: an XML parser context * @ret: an XML parser input * * Check an input in case it was created from an HTTP stream, in that * case it will handle encoding and update of the base URL in case of * redirection. It also checks for HTTP errors in which case the input * is cleanly freed up and an appropriate error is raised in context * * Returns the input or NULL in case of HTTP error. */ xmlParserInputPtr xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { #ifdef LIBXML_HTTP_ENABLED if ((ret != NULL) && (ret->buf != NULL) && (ret->buf->readcallback == xmlIOHTTPRead) && (ret->buf->context != NULL)) { const char *encoding; const char *redir; const char *mime; int code; code = xmlNanoHTTPReturnCode(ret->buf->context); if (code >= 400) { /* fatal error */ if (ret->filename != NULL) __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n", (const char *) ret->filename); else __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL); xmlFreeInputStream(ret); ret = NULL; } else { mime = xmlNanoHTTPMimeType(ret->buf->context); if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) || (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) { encoding = xmlNanoHTTPEncoding(ret->buf->context); if (encoding != NULL) { xmlCharEncodingHandlerPtr handler; handler = xmlFindCharEncodingHandler(encoding); if (handler != NULL) { xmlSwitchInputEncoding(ctxt, ret, handler); } else { __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING, "Unknown encoding %s", BAD_CAST encoding, NULL); } if (ret->encoding == NULL) ret->encoding = xmlStrdup(BAD_CAST encoding); } #if 0 } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) { #endif } redir = xmlNanoHTTPRedir(ret->buf->context); if (redir != NULL) { if (ret->filename != NULL) xmlFree((xmlChar *) ret->filename); if (ret->directory != NULL) { xmlFree((xmlChar *) ret->directory); ret->directory = NULL; } ret->filename = (char *) xmlStrdup((const xmlChar *) redir); } } } #endif return(ret); } static int xmlSysIDExists(const char *URL) { #ifdef HAVE_STAT int ret; struct stat info; const char *path; if (URL == NULL) return(0); if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17)) #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &URL[17]; #else path = &URL[16]; #endif else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) { #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &URL[8]; #else path = &URL[7]; #endif } else path = URL; ret = stat(path, &info); if (ret == 0) return(1); #endif return(0); } /** * xmlDefaultExternalEntityLoader: * @URL: the URL for the entity to load * @ID: the System ID for the entity to load * @ctxt: the context in which the entity is called or NULL * * By default we don't load external entitites, yet. * * Returns a new allocated xmlParserInputPtr, or NULL. */ static xmlParserInputPtr xmlDefaultExternalEntityLoader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt) { xmlParserInputPtr ret = NULL; xmlChar *resource = NULL; #ifdef LIBXML_CATALOG_ENABLED xmlCatalogAllow pref; #endif #ifdef DEBUG_EXTERNAL_ENTITIES xmlGenericError(xmlGenericErrorContext, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL); #endif #ifdef LIBXML_CATALOG_ENABLED if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) { int options = ctxt->options; ctxt->options -= XML_PARSE_NONET; ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); ctxt->options = options; return(ret); } /* * If the resource doesn't exists as a file, * try to load it from the resource pointed in the catalogs */ pref = xmlCatalogGetDefaults(); if ((pref != XML_CATA_ALLOW_NONE) && (!xmlSysIDExists(URL))) { /* * Do a local lookup */ if ((ctxt != NULL) && (ctxt->catalogs != NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_DOCUMENT))) { resource = xmlCatalogLocalResolve(ctxt->catalogs, (const xmlChar *) ID, (const xmlChar *) URL); } /* * Try a global lookup */ if ((resource == NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_GLOBAL))) { resource = xmlCatalogResolve((const xmlChar *) ID, (const xmlChar *) URL); } if ((resource == NULL) && (URL != NULL)) resource = xmlStrdup((const xmlChar *) URL); /* * TODO: do an URI lookup on the reference */ if ((resource != NULL) && (!xmlSysIDExists((const char *) resource))) { xmlChar *tmp = NULL; if ((ctxt != NULL) && (ctxt->catalogs != NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_DOCUMENT))) { tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource); } if ((tmp == NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_GLOBAL))) { tmp = xmlCatalogResolveURI(resource); } if (tmp != NULL) { xmlFree(resource); resource = tmp; } } } #endif if (resource == NULL) resource = (xmlChar *) URL; if (resource == NULL) { if (ID == NULL) ID = "NULL"; __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID); return (NULL); } ret = xmlNewInputFromFile(ctxt, (const char *) resource); if ((resource != NULL) && (resource != (xmlChar *) URL)) xmlFree(resource); return (ret); } static xmlExternalEntityLoader xmlCurrentExternalEntityLoader = xmlDefaultExternalEntityLoader; /** * xmlSetExternalEntityLoader: * @f: the new entity resolver function * * Changes the defaultexternal entity resolver function for the application */ void xmlSetExternalEntityLoader(xmlExternalEntityLoader f) { xmlCurrentExternalEntityLoader = f; } /** * xmlGetExternalEntityLoader: * * Get the default external entity resolver function for the application * * Returns the xmlExternalEntityLoader function pointer */ xmlExternalEntityLoader xmlGetExternalEntityLoader(void) { return(xmlCurrentExternalEntityLoader); } /** * xmlLoadExternalEntity: * @URL: the URL for the entity to load * @ID: the Public ID for the entity to load * @ctxt: the context in which the entity is called or NULL * * Load an external entity, note that the use of this function for * unparsed entities may generate problems * * Returns the xmlParserInputPtr or NULL */ xmlParserInputPtr xmlLoadExternalEntity(const char *URL, const char *ID, xmlParserCtxtPtr ctxt) { if ((URL != NULL) && (xmlSysIDExists(URL) == 0)) { char *canonicFilename; xmlParserInputPtr ret; canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL); if (canonicFilename == NULL) { xmlIOErrMemory("building canonical path\n"); return(NULL); } ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt); xmlFree(canonicFilename); return(ret); } return(xmlCurrentExternalEntityLoader(URL, ID, ctxt)); } /************************************************************************ * * * Disabling Network access * * * ************************************************************************/ #ifdef LIBXML_CATALOG_ENABLED static int xmlNoNetExists(const char *URL) { #ifdef HAVE_STAT int ret; struct stat info; const char *path; if (URL == NULL) return (0); if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17)) #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &URL[17]; #else path = &URL[16]; #endif else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) { #if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) path = &URL[8]; #else path = &URL[7]; #endif } else path = URL; ret = stat(path, &info); if (ret == 0) return (1); #endif return (0); } #endif /** * xmlNoNetExternalEntityLoader: * @URL: the URL for the entity to load * @ID: the System ID for the entity to load * @ctxt: the context in which the entity is called or NULL * * A specific entity loader disabling network accesses, though still * allowing local catalog accesses for resolution. * * Returns a new allocated xmlParserInputPtr, or NULL. */ xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt) { xmlParserInputPtr input = NULL; xmlChar *resource = NULL; #ifdef LIBXML_CATALOG_ENABLED xmlCatalogAllow pref; /* * If the resource doesn't exists as a file, * try to load it from the resource pointed in the catalogs */ pref = xmlCatalogGetDefaults(); if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) { /* * Do a local lookup */ if ((ctxt != NULL) && (ctxt->catalogs != NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_DOCUMENT))) { resource = xmlCatalogLocalResolve(ctxt->catalogs, (const xmlChar *)ID, (const xmlChar *)URL); } /* * Try a global lookup */ if ((resource == NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_GLOBAL))) { resource = xmlCatalogResolve((const xmlChar *)ID, (const xmlChar *)URL); } if ((resource == NULL) && (URL != NULL)) resource = xmlStrdup((const xmlChar *) URL); /* * TODO: do an URI lookup on the reference */ if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) { xmlChar *tmp = NULL; if ((ctxt != NULL) && (ctxt->catalogs != NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_DOCUMENT))) { tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource); } if ((tmp == NULL) && ((pref == XML_CATA_ALLOW_ALL) || (pref == XML_CATA_ALLOW_GLOBAL))) { tmp = xmlCatalogResolveURI(resource); } if (tmp != NULL) { xmlFree(resource); resource = tmp; } } } #endif if (resource == NULL) resource = (xmlChar *) URL; if (resource != NULL) { if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) || (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) { xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource); if (resource != (xmlChar *) URL) xmlFree(resource); return(NULL); } } input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt); if (resource != (xmlChar *) URL) xmlFree(resource); return(input); } #define bottom_xmlIO #include "elfgcchack.h"
xmlIO.c
Page URL
File URL
Prev
102/114
Next
Download
( 99 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.