📄 xmlio.c
字号:
* @len: number of bytes to write * * Write @len bytes from @buffer to the xml buffer * * Returns the number of bytes written */static intxmlBufferWrite (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 intxmlGzfileMatch (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 intxmlGzfileRead (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 intxmlGzfileWrite (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 intxmlGzfileClose (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_ENABLEDtypedef 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 voidappend_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 voidxmlFreeZMemBuff( 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 intxmlZMemBuffExtend( 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 intxmlZMemBuffAppend( 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 intxmlZMemBuffGetContent( 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 ); } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -