2001-02-23 17:55:21 +00:00
/*
* xmlIO . c : implementation of the I / O interfaces used by the parser
*
* See Copyright for the status of this software .
*
2001-08-20 00:08:40 +00:00
* daniel @ veillard . com
2001-02-23 17:55:21 +00:00
*
* 14 Nov 2000 ht - for VMS , truncated name of long functions to under 32 char
*/
2002-03-18 19:37:11 +00:00
# define IN_LIBXML
2001-04-21 16:57:29 +00:00
# include "libxml.h"
2001-02-23 17:55:21 +00:00
# include <string.h>
2002-09-17 17:59:20 +00:00
# ifdef HAVE_ERRNO_H
2001-02-23 17:55:21 +00:00
# include <errno.h>
2002-09-17 17:59:20 +00:00
# endif
2001-02-23 17:55:21 +00:00
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
# ifdef HAVE_FCNTL_H
# include <fcntl.h>
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
# ifdef HAVE_ZLIB_H
# include <zlib.h>
# endif
/* Figure a portable way to know if a file is a directory. */
# ifndef HAVE_STAT
# ifdef HAVE__STAT
2001-08-03 12:06:36 +00:00
/* 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
2001-02-23 17:55:21 +00:00
# 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 <libxml/xmlmemory.h>
# include <libxml/parser.h>
# include <libxml/parserInternals.h>
# include <libxml/xmlIO.h>
2001-07-08 18:35:48 +00:00
# include <libxml/uri.h>
2001-02-23 17:55:21 +00:00
# include <libxml/nanohttp.h>
# include <libxml/nanoftp.h>
# include <libxml/xmlerror.h>
2001-05-10 15:34:11 +00:00
# ifdef LIBXML_CATALOG_ENABLED
# include <libxml/catalog.h>
# endif
2001-10-17 15:58:35 +00:00
# include <libxml/globals.h>
2001-02-23 17:55:21 +00:00
2001-07-23 19:10:52 +00:00
/* #define VERBOSE_FAILURE */
2001-07-04 22:54:28 +00:00
/* #define DEBUG_EXTERNAL_ENTITIES */
2001-02-23 17:55:21 +00:00
/* #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
2001-07-16 00:06:07 +00:00
static xmlInputCallback xmlInputCallbackTable [ MAX_INPUT_CALLBACK ] ;
static int xmlInputCallbackNr = 0 ;
static int xmlInputCallbackInitialized = 0 ;
2001-02-23 17:55:21 +00:00
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/*
* Output I / O callback sets
*/
typedef struct _xmlOutputCallback {
xmlOutputMatchCallback matchcallback ;
xmlOutputOpenCallback opencallback ;
xmlOutputWriteCallback writecallback ;
xmlOutputCloseCallback closecallback ;
} xmlOutputCallback ;
# define MAX_OUTPUT_CALLBACK 15
2001-07-16 00:06:07 +00:00
static xmlOutputCallback xmlOutputCallbackTable [ MAX_OUTPUT_CALLBACK ] ;
static int xmlOutputCallbackNr = 0 ;
static int xmlOutputCallbackInitialized = 0 ;
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
2003-10-08 11:54:57 +00:00
/************************************************************************
* *
* Tree memory error handler *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * IOerr [ ] = {
2003-10-08 19:26:03 +00:00
" Unknown IO error " , /* UNKNOWN */
2003-10-08 11:54:57 +00:00
" 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 */
2003-10-10 19:36:36 +00:00
" Attempt to load network entity %s " , /* XML_IO_NETWORK_ATTEMPT */
2003-10-08 11:54:57 +00:00
" encoder error " , /* XML_IO_ENCODER */
2003-10-10 19:36:36 +00:00
" flush error " ,
" write error " ,
" no input " ,
" buffer full " ,
" loading error " ,
" not a socket " , /* ENOTSOCK */
" already connected " , /* EISCONN */
" connection refuxed " , /* ECONNREFUSED */
" unreachable network " , /* ENETUNREACH */
" adddress in use " , /* EADDRINUSE */
" already in use " , /* EALREADY */
" unknown address familly " , /* EAFNOSUPPORT */
2003-10-08 11:54:57 +00:00
} ;
/**
* 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 ) ;
}
/**
2003-10-10 19:36:36 +00:00
* __xmlIOErr :
2003-10-08 11:54:57 +00:00
* @ code : the error number
2003-10-10 19:36:36 +00:00
* @
2003-10-08 11:54:57 +00:00
* @ extra : extra informations
*
2003-10-08 22:38:13 +00:00
* Handle an I / O error
2003-10-08 11:54:57 +00:00
*/
2003-10-10 19:36:36 +00:00
void
__xmlIOErr ( int domain , int code , const char * extra )
2003-10-08 11:54:57 +00:00
{
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 ;
2003-10-10 19:36:36 +00:00
# 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 ;
2003-10-08 11:54:57 +00:00
# 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 ;
2003-10-10 19:36:36 +00:00
__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 ) ;
2003-10-08 11:54:57 +00:00
}
2002-09-10 11:13:43 +00:00
2003-10-08 22:38:13 +00:00
/**
2003-10-27 11:25:13 +00:00
* __xmlLoaderErr :
* @ ctx : the parser context
2003-10-08 22:38:13 +00:00
* @ extra : extra informations
*
* Handle a resource access error
*/
2003-10-27 11:25:13 +00:00
void
__xmlLoaderErr ( void * ctx , const char * msg , const char * filename )
2003-10-08 22:38:13 +00:00
{
2003-10-27 11:25:13 +00:00
xmlParserCtxtPtr ctxt = ( xmlParserCtxtPtr ) ctx ;
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-08 22:38:13 +00:00
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
xmlErrorLevel level = XML_ERR_ERROR ;
2003-10-31 10:36:03 +00:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > disableSAX ! = 0 ) & &
( ctxt - > instate = = XML_PARSER_EOF ) )
return ;
2003-10-08 22:38:13 +00:00
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 ;
}
2003-10-10 14:10:40 +00:00
schannel = ctxt - > sax - > serror ;
2003-10-08 22:38:13 +00:00
data = ctxt - > userData ;
}
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data , ctxt , NULL , XML_FROM_IO ,
2003-10-08 22:38:13 +00:00
XML_IO_LOAD_ERROR , level , NULL , 0 ,
filename , NULL , NULL , 0 , 0 ,
msg , filename ) ;
}
2003-10-08 11:54:57 +00:00
/************************************************************************
* *
* Tree memory error handler *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-10 11:13:43 +00:00
/**
2002-12-10 15:19:08 +00:00
* xmlNormalizeWindowsPath :
2003-04-17 09:09:19 +00:00
* @ path : the input file path
2002-09-10 11:13:43 +00:00
*
2003-02-19 14:51:00 +00:00
* This function is obsolete . Please see xmlURIFromPath in uri . c for
* a better solution .
2003-04-17 09:09:19 +00:00
*
* Returns a canonicalized version of the path
2002-09-10 11:13:43 +00:00
*/
xmlChar *
xmlNormalizeWindowsPath ( const xmlChar * path )
{
2003-02-19 14:51:00 +00:00
return xmlCanonicPath ( path ) ;
2002-09-10 11:13:43 +00:00
}
2001-10-29 20:21:47 +00:00
/**
* xmlCleanupInputCallbacks :
*
* clears the entire input callback table . this includes the
* compiled - in I / O .
*/
void
xmlCleanupInputCallbacks ( void )
{
int i ;
if ( ! xmlInputCallbackInitialized )
return ;
2001-11-27 16:23:50 +00:00
for ( i = xmlInputCallbackNr - 1 ; i > = 0 ; i - - ) {
2001-10-29 20:21:47 +00:00
xmlInputCallbackTable [ i ] . matchcallback = NULL ;
xmlInputCallbackTable [ i ] . opencallback = NULL ;
xmlInputCallbackTable [ i ] . readcallback = NULL ;
xmlInputCallbackTable [ i ] . closecallback = NULL ;
}
xmlInputCallbackNr = 0 ;
2002-06-06 21:46:13 +00:00
xmlInputCallbackInitialized = 0 ;
2001-10-29 20:21:47 +00:00
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-10-29 20:21:47 +00:00
/**
* xmlCleanupOutputCallbacks :
*
* clears the entire output callback table . this includes the
* compiled - in I / O callbacks .
*/
void
xmlCleanupOutputCallbacks ( void )
{
int i ;
if ( ! xmlOutputCallbackInitialized )
return ;
2001-11-27 16:23:50 +00:00
for ( i = xmlOutputCallbackNr - 1 ; i > = 0 ; i - - ) {
2001-10-29 20:21:47 +00:00
xmlOutputCallbackTable [ i ] . matchcallback = NULL ;
xmlOutputCallbackTable [ i ] . opencallback = NULL ;
xmlOutputCallbackTable [ i ] . writecallback = NULL ;
xmlOutputCallbackTable [ i ] . closecallback = NULL ;
}
xmlOutputCallbackNr = 0 ;
2002-06-06 21:46:13 +00:00
xmlOutputCallbackInitialized = 0 ;
2001-10-29 20:21:47 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-10-29 20:21:47 +00:00
2001-02-23 17:55:21 +00:00
/************************************************************************
* *
* Standard I / O for file accesses *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
2002-12-11 14:23:49 +00:00
* xmlCheckFilename :
2001-02-23 17:55:21 +00:00
* @ 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 ,
2002-10-14 11:15:18 +00:00
* returns 2. otherwise returns 1.
2001-02-23 17:55:21 +00:00
*/
2002-10-14 11:15:18 +00:00
int
2001-02-23 17:55:21 +00:00
xmlCheckFilename ( const char * path )
{
# ifdef HAVE_STAT
struct stat stat_buffer ;
if ( stat ( path , & stat_buffer ) = = - 1 )
return 0 ;
2002-10-14 11:15:18 +00:00
# ifdef S_ISDIR
2001-02-23 17:55:21 +00:00
if ( S_ISDIR ( stat_buffer . st_mode ) ) {
2002-10-14 11:15:18 +00:00
return 2 ;
2001-02-23 17:55:21 +00:00
}
# endif
# endif
return 1 ;
}
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
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
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlFdRead ( void * context , char * buffer , int len ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = read ( ( int ) ( long ) context , & buffer [ 0 ] , len ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " read() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlFdWrite ( void * context , const char * buffer , int len ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = write ( ( int ) ( long ) context , & buffer [ 0 ] , len ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " write() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* xmlFdClose :
* @ context : the I / O context
*
* Close an I / O channel
2001-07-23 19:10:52 +00:00
*
* Returns 0 in case of success and error code otherwise
2001-02-23 17:55:21 +00:00
*/
2001-07-23 19:10:52 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlFdClose ( void * context ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = close ( ( int ) ( long ) context ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " close() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
/**
* xmlFileMatch :
* @ filename : the URI for matching
*
* input from FILE *
*
* Returns 1 if matches , 0 otherwise
*/
2002-05-01 18:32:28 +00:00
int
2001-03-26 16:28:29 +00:00
xmlFileMatch ( const char * filename ATTRIBUTE_UNUSED ) {
2001-02-23 17:55:21 +00:00
return ( 1 ) ;
}
/**
2003-01-10 16:09:51 +00:00
* xmlFileOpen_real :
2001-02-23 17:55:21 +00:00
* @ 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
*/
2003-01-10 16:09:51 +00:00
static void *
xmlFileOpen_real ( const char * filename ) {
2001-02-23 17:55:21 +00:00
const char * path = NULL ;
FILE * fd ;
if ( ! strcmp ( filename , " - " ) ) {
fd = stdin ;
return ( ( void * ) fd ) ;
}
2002-09-10 11:13:43 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2002-08-25 14:39:16 +00:00
path = & filename [ 17 ] ;
# else
2001-02-23 17:55:21 +00:00
path = & filename [ 16 ] ;
2002-08-25 14:39:16 +00:00
# endif
2002-05-01 18:32:28 +00:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2001-08-14 12:18:09 +00:00
path = & filename [ 8 ] ;
# else
2001-05-31 18:43:43 +00:00
path = & filename [ 7 ] ;
2001-08-14 12:18:09 +00:00
# endif
} else
2001-02-23 17:55:21 +00:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
if ( ! xmlCheckFilename ( path ) )
return ( NULL ) ;
2003-07-05 20:43:43 +00:00
# if defined(WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2001-02-23 17:55:21 +00:00
fd = fopen ( path , " rb " ) ;
# else
fd = fopen ( path , " r " ) ;
# endif /* WIN32 */
2003-10-08 11:54:57 +00:00
if ( fd = = NULL ) xmlIOErr ( 0 , path ) ;
2001-02-23 17:55:21 +00:00
return ( ( void * ) fd ) ;
}
2003-01-10 16:09:51 +00:00
/**
* 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
2003-02-05 13:19:53 +00:00
*
* Returns a handler or NULL in case or failure
2003-01-10 16:09:51 +00:00
*/
void *
xmlFileOpen ( const char * filename ) {
char * unescaped ;
void * retval ;
unescaped = xmlURIUnescapeString ( filename , 0 , NULL ) ;
if ( unescaped ! = NULL ) {
retval = xmlFileOpen_real ( unescaped ) ;
} else {
retval = xmlFileOpen_real ( filename ) ;
}
xmlFree ( unescaped ) ;
return retval ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2001-03-24 17:00:36 +00:00
static void *
2001-02-23 17:55:21 +00:00
xmlFileOpenW ( const char * filename ) {
const char * path = NULL ;
FILE * fd ;
if ( ! strcmp ( filename , " - " ) ) {
fd = stdout ;
return ( ( void * ) fd ) ;
}
2002-09-10 11:13:43 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2002-09-10 11:13:43 +00:00
path = & filename [ 17 ] ;
# else
2001-02-23 17:55:21 +00:00
path = & filename [ 16 ] ;
2002-09-10 11:13:43 +00:00
# endif
2002-05-01 18:32:28 +00:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2001-08-14 12:18:09 +00:00
path = & filename [ 8 ] ;
# else
2001-05-31 18:43:43 +00:00
path = & filename [ 7 ] ;
2001-08-14 12:18:09 +00:00
# endif
} else
2001-02-23 17:55:21 +00:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
2003-07-20 15:21:30 +00:00
fd = fopen ( path , " wb " ) ;
2003-10-08 11:54:57 +00:00
if ( fd = = NULL ) xmlIOErr ( 0 , path ) ;
2001-02-23 17:55:21 +00:00
return ( ( void * ) fd ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlFileRead ( void * context , char * buffer , int len ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = fread ( & buffer [ 0 ] , 1 , len , ( FILE * ) context ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " fread() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlFileWrite ( void * context , const char * buffer , int len ) {
2002-12-17 18:33:01 +00:00
int items ;
items = fwrite ( & buffer [ 0 ] , len , 1 , ( FILE * ) context ) ;
2003-10-08 18:58:28 +00:00
if ( ( items = = 0 ) & & ( ferror ( ( FILE * ) context ) ) ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( 0 , " fwrite() " ) ;
2003-10-08 18:58:28 +00:00
return ( - 1 ) ;
}
2002-12-17 18:33:01 +00:00
return ( items * len ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* xmlFileClose :
* @ context : the I / O context
*
* Close an I / O channel
2002-12-11 14:23:49 +00:00
*
* Returns 0 or - 1 in case of error
2001-02-23 17:55:21 +00:00
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlFileClose ( void * context ) {
2001-10-30 10:32:36 +00:00
FILE * fil ;
2003-10-08 11:54:57 +00:00
int ret ;
2001-10-30 10:32:36 +00:00
fil = ( FILE * ) context ;
if ( fil = = stdin )
return ( 0 ) ;
if ( fil = = stdout )
return ( 0 ) ;
2001-11-22 18:20:37 +00:00
if ( fil = = stderr )
return ( 0 ) ;
2003-10-08 11:54:57 +00:00
ret = ( fclose ( ( FILE * ) context ) = = EOF ) ? - 1 : 0 ;
if ( ret < 0 )
xmlIOErr ( 0 , " fclose() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
/**
* xmlFileFlush :
* @ context : the I / O context
*
* Flush an I / O channel
*/
2001-07-23 19:10:52 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlFileFlush ( void * context ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = ( fflush ( ( FILE * ) context ) = = EOF ) ? - 1 : 0 ;
if ( ret < 0 )
xmlIOErr ( 0 , " fflush() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
# 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
*/
2001-03-24 17:00:36 +00:00
static int
2001-03-26 16:28:29 +00:00
xmlGzfileMatch ( const char * filename ATTRIBUTE_UNUSED ) {
2001-02-23 17:55:21 +00:00
return ( 1 ) ;
}
/**
2003-01-10 16:09:51 +00:00
* xmlGzfileOpen_real :
2001-02-23 17:55:21 +00:00
* @ 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
*/
2001-03-24 17:00:36 +00:00
static void *
2003-01-10 16:09:51 +00:00
xmlGzfileOpen_real ( const char * filename ) {
2001-02-23 17:55:21 +00:00
const char * path = NULL ;
gzFile fd ;
if ( ! strcmp ( filename , " - " ) ) {
2001-10-30 10:32:36 +00:00
fd = gzdopen ( dup ( 0 ) , " rb " ) ;
2001-02-23 17:55:21 +00:00
return ( ( void * ) fd ) ;
}
2002-09-10 11:13:43 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2002-09-10 11:13:43 +00:00
path = & filename [ 17 ] ;
# else
2001-02-23 17:55:21 +00:00
path = & filename [ 16 ] ;
2002-09-10 11:13:43 +00:00
# endif
2002-05-01 18:32:28 +00:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2001-08-14 12:18:09 +00:00
path = & filename [ 8 ] ;
# else
2001-02-23 17:55:21 +00:00
path = & filename [ 7 ] ;
2001-08-14 12:18:09 +00:00
# endif
} else
2001-02-23 17:55:21 +00:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
if ( ! xmlCheckFilename ( path ) )
return ( NULL ) ;
fd = gzopen ( path , " rb " ) ;
return ( ( void * ) fd ) ;
}
2003-01-10 16:09:51 +00:00
/**
* xmlGzfileOpen :
* @ filename : the URI for matching
*
2003-06-09 10:30:33 +00:00
* Wrapper around xmlGzfileOpen if the open fais , it will
* try to unescape @ filename
2003-01-10 16:09:51 +00:00
*/
static void *
xmlGzfileOpen ( const char * filename ) {
char * unescaped ;
void * retval ;
2003-06-09 10:30:33 +00:00
retval = xmlGzfileOpen_real ( filename ) ;
if ( retval = = NULL ) {
unescaped = xmlURIUnescapeString ( filename , 0 , NULL ) ;
if ( unescaped ! = NULL ) {
retval = xmlGzfileOpen_real ( unescaped ) ;
}
xmlFree ( unescaped ) ;
2003-01-10 16:09:51 +00:00
}
return retval ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2001-03-24 17:00:36 +00:00
static void *
2001-02-23 17:55:21 +00:00
xmlGzfileOpenW ( const char * filename , int compression ) {
const char * path = NULL ;
char mode [ 15 ] ;
gzFile fd ;
2002-06-14 17:07:10 +00:00
snprintf ( mode , sizeof ( mode ) , " wb%d " , compression ) ;
2001-02-23 17:55:21 +00:00
if ( ! strcmp ( filename , " - " ) ) {
2001-10-30 10:32:36 +00:00
fd = gzdopen ( dup ( 1 ) , mode ) ;
2001-02-23 17:55:21 +00:00
return ( ( void * ) fd ) ;
}
2002-09-10 11:13:43 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2002-09-10 11:13:43 +00:00
path = & filename [ 17 ] ;
# else
2001-02-23 17:55:21 +00:00
path = & filename [ 16 ] ;
2002-09-10 11:13:43 +00:00
# endif
2002-05-01 18:32:28 +00:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2001-08-14 12:18:09 +00:00
path = & filename [ 8 ] ;
# else
2001-05-31 18:43:43 +00:00
path = & filename [ 7 ] ;
2001-08-14 12:18:09 +00:00
# endif
} else
2001-02-23 17:55:21 +00:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
fd = gzopen ( path , mode ) ;
return ( ( void * ) fd ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlGzfileRead ( void * context , char * buffer , int len ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = gzread ( ( gzFile ) context , & buffer [ 0 ] , len ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " gzread() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlGzfileWrite ( void * context , const char * buffer , int len ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = gzwrite ( ( gzFile ) context , ( char * ) & buffer [ 0 ] , len ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " gzwrite() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* xmlGzfileClose :
* @ context : the I / O context
*
* Close a compressed I / O channel
*/
2001-07-23 19:10:52 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlGzfileClose ( void * context ) {
2003-10-08 11:54:57 +00:00
int ret ;
ret = ( gzclose ( ( gzFile ) context ) = = Z_OK ) ? 0 : - 1 ;
if ( ret < 0 ) xmlIOErr ( 0 , " gzclose() " ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
# endif /* HAVE_ZLIB_H */
# ifdef LIBXML_HTTP_ENABLED
/************************************************************************
* *
* I / O for HTTP file accesses *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-07-23 19:10:52 +00:00
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 19:10:52 +00:00
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 ) {
2003-07-31 14:47:38 +00:00
# ifdef DEBUG_HTTP
2001-07-23 19:10:52 +00:00
int z_err ;
2003-07-31 14:47:38 +00:00
# endif
2001-07-23 19:10:52 +00:00
if ( buff = = NULL )
return ;
xmlFree ( buff - > zbuff ) ;
# ifdef DEBUG_HTTP
2003-07-31 14:47:38 +00:00
z_err = deflateEnd ( & buff - > zctrl ) ;
2001-07-23 19:10:52 +00:00
if ( z_err ! = Z_OK )
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeZMemBuff: Error releasing zlib context: %d \n " ,
z_err ) ;
2003-07-31 14:47:38 +00:00
# else
deflateEnd ( & buff - > zctrl ) ;
2003-08-01 15:55:39 +00:00
# endif
2001-07-23 19:10:52 +00:00
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 ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " creating buffer context " ) ;
2001-07-23 19:10:52 +00:00
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 ) ;
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " creating buffer " ) ;
2001-07-23 19:10:52 +00:00
return ( NULL ) ;
}
z_err = deflateInit2 ( & buff - > zctrl , compression , Z_DEFLATED ,
DFLT_WBITS , DFLT_MEM_LVL , Z_DEFAULT_STRATEGY ) ;
if ( z_err ! = Z_OK ) {
2003-10-08 11:54:57 +00:00
xmlChar msg [ 500 ] ;
2001-07-23 19:10:52 +00:00
xmlFreeZMemBuff ( buff ) ;
buff = NULL ;
2003-10-08 11:54:57 +00:00
xmlStrPrintf ( msg , 500 ,
( const xmlChar * ) " xmlCreateZMemBuff: %s %d \n " ,
" Error initializing compression context. ZLIB error: " ,
z_err ) ;
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 19:10:52 +00:00
return ( NULL ) ;
}
/* Set the header data. The CRC will be needed for the trailer */
buff - > crc = crc32 ( 0L , Z_NULL , 0 ) ;
2002-06-14 17:07:10 +00:00
hdr_lgth = snprintf ( ( char * ) buff - > zbuff , buff - > size ,
" %c%c%c%c%c%c%c%c%c%c " ,
2001-07-23 19:10:52 +00:00
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 {
2003-10-08 11:54:57 +00:00
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 ) ;
2001-07-23 19:10:52 +00:00
}
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 ) {
2003-10-08 11:54:57 +00:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
( const xmlChar * ) " xmlZMemBuffAppend: %s %d %s - %d " ,
2001-07-23 19:10:52 +00:00
" Compression error while appending " ,
len , " bytes to buffer. ZLIB error " , z_err ) ;
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 19:10:52 +00:00
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 ;
}
2003-10-08 11:54:57 +00:00
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 ) ;
}
2001-07-23 19:10:52 +00:00
return ( zlgth ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
# endif /* HAVE_ZLIB_H */
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 19:10:52 +00:00
/**
* xmlFreeHTTPWriteCtxt
* @ ctxt : Context to cleanup
*
* Free allocated memory and reclaim system resources .
*
* No return value .
*/
static void
xmlFreeHTTPWriteCtxt ( xmlIOHTTPWriteCtxtPtr ctxt )
{
if ( ctxt - > uri ! = NULL )
2002-10-14 11:15:18 +00:00
xmlFree ( ctxt - > uri ) ;
2001-07-23 19:10:52 +00:00
if ( ctxt - > doc_buff ! = NULL ) {
# ifdef HAVE_ZLIB_H
if ( ctxt - > compression > 0 ) {
xmlFreeZMemBuff ( ctxt - > doc_buff ) ;
}
else
# endif
{
xmlOutputBufferClose ( ctxt - > doc_buff ) ;
}
}
2002-10-14 11:15:18 +00:00
xmlFree ( ctxt ) ;
2001-07-23 19:10:52 +00:00
return ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
2001-02-23 17:55:21 +00:00
/**
* xmlIOHTTPMatch :
* @ filename : the URI for matching
*
* check if the URI matches an HTTP one
*
* Returns 1 if matches , 0 otherwise
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlIOHTTPMatch ( const char * filename ) {
2002-05-01 18:32:28 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " http:// " , 7 ) )
2001-02-23 17:55:21 +00:00
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
*/
2002-05-01 18:32:28 +00:00
void *
2001-02-23 17:55:21 +00:00
xmlIOHTTPOpen ( const char * filename ) {
return ( xmlNanoHTTPOpen ( filename , NULL ) ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 19:10:52 +00:00
/**
2002-12-11 14:23:49 +00:00
* xmlIOHTTPOpenW :
2001-07-23 19:10:52 +00:00
* @ 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 *
2002-01-18 16:23:55 +00:00
xmlIOHTTPOpenW ( const char * post_uri , int compression )
{
2001-07-23 19:10:52 +00:00
2002-01-18 16:23:55 +00:00
xmlIOHTTPWriteCtxtPtr ctxt = NULL ;
2001-07-23 19:10:52 +00:00
2002-01-18 16:23:55 +00:00
if ( post_uri = = NULL )
return ( NULL ) ;
2001-07-23 19:10:52 +00:00
2002-01-18 16:23:55 +00:00
ctxt = xmlMalloc ( sizeof ( xmlIOHTTPWriteCtxt ) ) ;
if ( ctxt = = NULL ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " creating HTTP output context " ) ;
2002-01-18 16:23:55 +00:00
return ( NULL ) ;
2001-07-23 19:10:52 +00:00
}
2002-01-18 16:23:55 +00:00
( void ) memset ( ctxt , 0 , sizeof ( xmlIOHTTPWriteCtxt ) ) ;
2001-07-23 19:10:52 +00:00
2002-01-18 16:23:55 +00:00
ctxt - > uri = ( char * ) xmlStrdup ( ( const xmlChar * ) post_uri ) ;
if ( ctxt - > uri = = NULL ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " copying URI " ) ;
2002-01-18 16:23:55 +00:00
xmlFreeHTTPWriteCtxt ( ctxt ) ;
return ( NULL ) ;
2001-07-23 19:10:52 +00:00
}
/*
2002-01-18 16:23:55 +00:00
* * * 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 .
*/
2001-07-23 19:10:52 +00:00
# ifdef HAVE_ZLIB_H
2002-01-18 16:23:55 +00:00
if ( ( compression > 0 ) & & ( compression < = 9 ) ) {
ctxt - > compression = compression ;
ctxt - > doc_buff = xmlCreateZMemBuff ( compression ) ;
} else
2001-07-23 19:10:52 +00:00
# endif
{
2002-01-18 16:23:55 +00:00
/* Any character conversions should have been done before this */
2001-07-23 19:10:52 +00:00
2002-01-18 16:23:55 +00:00
ctxt - > doc_buff = xmlAllocOutputBuffer ( NULL ) ;
2001-07-23 19:10:52 +00:00
}
2002-01-18 16:23:55 +00:00
if ( ctxt - > doc_buff = = NULL ) {
xmlFreeHTTPWriteCtxt ( ctxt ) ;
ctxt = NULL ;
2001-07-23 19:10:52 +00:00
}
2002-01-18 16:23:55 +00:00
return ( ctxt ) ;
2001-07-23 19:10:52 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 19:10:52 +00:00
/**
* 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 ) ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
2001-02-23 17:55:21 +00:00
/**
* 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
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlIOHTTPRead ( void * context , char * buffer , int len ) {
return ( xmlNanoHTTPRead ( context , & buffer [ 0 ] , len ) ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 19:10:52 +00:00
/**
* 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 ) {
2003-10-08 11:54:57 +00:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
( const xmlChar * ) " xmlIOHTTPWrite: %s \n %s '%s'. \n " ,
2001-07-23 19:10:52 +00:00
" Error appending to internal buffer. " ,
" Error sending document to URI " ,
ctxt - > uri ) ;
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 19:10:52 +00:00
}
}
return ( len ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
2001-02-23 17:55:21 +00:00
/**
* xmlIOHTTPClose :
* @ context : the I / O context
*
* Close an HTTP I / O channel
2002-12-11 14:23:49 +00:00
*
* Returns 0
2001-02-23 17:55:21 +00:00
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlIOHTTPClose ( void * context ) {
xmlNanoHTTPClose ( context ) ;
2001-07-23 19:10:52 +00:00
return 0 ;
2001-02-23 17:55:21 +00:00
}
2001-07-23 19:10:52 +00:00
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 19:10:52 +00:00
/**
* 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 ) {
2003-10-08 11:54:57 +00:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
( const xmlChar * ) " xmlIOHTTPCloseWrite: %s '%s' %s '%s'. \n " ,
" Error retrieving content. \n Unable to " ,
http_mthd , " data to URI " , ctxt - > uri ) ;
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 19:10:52 +00:00
}
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 ) {
2002-06-14 17:07:10 +00:00
( void ) snprintf ( buffer , sizeof ( buffer ) , " %s.content " , dump_name ) ;
2001-07-23 19:10:52 +00:00
2003-07-20 15:21:30 +00:00
tst_file = fopen ( buffer , " wb " ) ;
2001-07-23 19:10:52 +00:00
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 ) ;
}
2002-06-14 17:07:10 +00:00
( void ) snprintf ( buffer , sizeof ( buffer ) , " %s.reply " , dump_name ) ;
2003-07-20 15:21:30 +00:00
tst_file = fopen ( buffer , " wb " ) ;
2001-07-23 19:10:52 +00:00
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 ;
2003-10-08 11:54:57 +00:00
else {
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
( const xmlChar * ) " xmlIOHTTPCloseWrite: HTTP '%s' of %d %s \n '%s' %s %d \n " ,
2001-07-23 19:10:52 +00:00
http_mthd , content_lgth ,
" bytes to URI " , ctxt - > uri ,
" failed. HTTP return code: " , http_rtn ) ;
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
}
2001-07-23 19:10:52 +00:00
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 " ) ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
2001-02-23 17:55:21 +00:00
# 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
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlIOFTPMatch ( const char * filename ) {
2002-05-01 18:32:28 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " ftp:// " , 6 ) )
2001-02-23 17:55:21 +00:00
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
*/
2002-05-01 18:32:28 +00:00
void *
2001-02-23 17:55:21 +00:00
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
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlIOFTPRead ( void * context , char * buffer , int len ) {
return ( xmlNanoFTPRead ( context , & buffer [ 0 ] , len ) ) ;
}
/**
* xmlIOFTPClose :
* @ context : the I / O context
*
* Close an FTP I / O channel
2002-12-11 14:23:49 +00:00
*
* Returns 0
2001-02-23 17:55:21 +00:00
*/
2002-05-01 18:32:28 +00:00
int
2001-02-23 17:55:21 +00:00
xmlIOFTPClose ( void * context ) {
2001-07-23 19:10:52 +00:00
return ( xmlNanoFTPClose ( context ) ) ;
2001-02-23 17:55:21 +00:00
}
# endif /* LIBXML_FTP_ENABLED */
/**
* xmlRegisterInputCallbacks :
2001-03-24 17:00:36 +00:00
* @ matchFunc : the xmlInputMatchCallback
* @ openFunc : the xmlInputOpenCallback
* @ readFunc : the xmlInputReadCallback
* @ closeFunc : the xmlInputCloseCallback
2001-02-23 17:55:21 +00:00
*
* Register a new set of I / O callback for handling parser input .
*
* Returns the registered handler number or - 1 in case of error
*/
int
2001-03-24 17:00:36 +00:00
xmlRegisterInputCallbacks ( xmlInputMatchCallback matchFunc ,
xmlInputOpenCallback openFunc , xmlInputReadCallback readFunc ,
xmlInputCloseCallback closeFunc ) {
2001-02-23 17:55:21 +00:00
if ( xmlInputCallbackNr > = MAX_INPUT_CALLBACK ) {
return ( - 1 ) ;
}
2001-03-24 17:00:36 +00:00
xmlInputCallbackTable [ xmlInputCallbackNr ] . matchcallback = matchFunc ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . opencallback = openFunc ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . readcallback = readFunc ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . closecallback = closeFunc ;
2003-09-23 07:43:19 +00:00
xmlInputCallbackInitialized = 1 ;
2001-02-23 17:55:21 +00:00
return ( xmlInputCallbackNr + + ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* xmlRegisterOutputCallbacks :
2001-03-24 17:00:36 +00:00
* @ matchFunc : the xmlOutputMatchCallback
* @ openFunc : the xmlOutputOpenCallback
* @ writeFunc : the xmlOutputWriteCallback
* @ closeFunc : the xmlOutputCloseCallback
2001-02-23 17:55:21 +00:00
*
* Register a new set of I / O callback for handling output .
*
* Returns the registered handler number or - 1 in case of error
*/
int
2001-03-24 17:00:36 +00:00
xmlRegisterOutputCallbacks ( xmlOutputMatchCallback matchFunc ,
xmlOutputOpenCallback openFunc , xmlOutputWriteCallback writeFunc ,
xmlOutputCloseCallback closeFunc ) {
2001-02-23 17:55:21 +00:00
if ( xmlOutputCallbackNr > = MAX_INPUT_CALLBACK ) {
return ( - 1 ) ;
}
2001-03-24 17:00:36 +00:00
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . matchcallback = matchFunc ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . opencallback = openFunc ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . writecallback = writeFunc ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . closecallback = closeFunc ;
2003-09-23 07:43:19 +00:00
xmlOutputCallbackInitialized = 1 ;
2001-02-23 17:55:21 +00:00
return ( xmlOutputCallbackNr + + ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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 ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* xmlRegisterDefaultOutputCallbacks :
*
* Registers the default compiled - in I / O handlers .
*/
void
xmlRegisterDefaultOutputCallbacks
( void ) {
if ( xmlOutputCallbackInitialized )
return ;
xmlRegisterOutputCallbacks ( xmlFileMatch , xmlFileOpenW ,
xmlFileWrite , xmlFileClose ) ;
2001-07-23 19:10:52 +00:00
# ifdef LIBXML_HTTP_ENABLED
xmlRegisterOutputCallbacks ( xmlIOHTTPMatch , xmlIOHTTPDfltOpenW ,
xmlIOHTTPWrite , xmlIOHTTPClosePut ) ;
# endif
2001-02-23 17:55:21 +00:00
/*********************************
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 ;
}
2001-07-23 19:10:52 +00:00
# ifdef LIBXML_HTTP_ENABLED
/**
2002-12-11 14:23:49 +00:00
* xmlRegisterHTTPPostCallbacks :
2001-07-23 19:10:52 +00:00
*
* 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
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 19:10:52 +00:00
2001-02-23 17:55:21 +00:00
/**
* 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 ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " creating input buffer " ) ;
2001-02-23 17:55:21 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , ( size_t ) sizeof ( xmlParserInputBuffer ) ) ;
2003-08-19 15:01:28 +00:00
ret - > buffer = xmlBufferCreateSize ( 2 * xmlDefaultBufferSize ) ;
2001-02-23 17:55:21 +00:00
if ( ret - > buffer = = NULL ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
ret - > buffer - > alloc = XML_BUFFER_ALLOC_DOUBLEIT ;
ret - > encoder = xmlGetCharEncodingHandler ( enc ) ;
if ( ret - > encoder ! = NULL )
2003-08-19 15:01:28 +00:00
ret - > raw = xmlBufferCreateSize ( 2 * xmlDefaultBufferSize ) ;
2001-02-23 17:55:21 +00:00
else
ret - > raw = NULL ;
ret - > readcallback = NULL ;
ret - > closecallback = NULL ;
ret - > context = NULL ;
2003-09-08 01:57:30 +00:00
ret - > compressed = - 1 ;
2004-02-11 13:25:26 +00:00
ret - > rawconsumed = 0 ;
2001-02-23 17:55:21 +00:00
return ( ret ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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 ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " creating output buffer " ) ;
2001-02-23 17:55:21 +00:00
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 ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* xmlFreeParserInputBuffer :
* @ in : a buffered parser input
*
* Free up the memory used by a buffered parser input
*/
void
xmlFreeParserInputBuffer ( xmlParserInputBufferPtr in ) {
2003-09-17 19:36:25 +00:00
if ( in = = NULL ) return ;
2001-02-23 17:55:21 +00:00
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 ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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
2003-10-08 19:19:10 +00:00
xmlOutputBufferClose ( xmlOutputBufferPtr out )
{
2001-02-23 17:55:21 +00:00
int written ;
2001-07-23 19:10:52 +00:00
int err_rc = 0 ;
2001-02-23 17:55:21 +00:00
if ( out = = NULL )
2003-10-08 19:19:10 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
if ( out - > writecallback ! = NULL )
2003-10-08 19:19:10 +00:00
xmlOutputBufferFlush ( out ) ;
2001-02-23 17:55:21 +00:00
if ( out - > closecallback ! = NULL ) {
2003-10-08 19:19:10 +00:00
err_rc = out - > closecallback ( out - > context ) ;
2001-02-23 17:55:21 +00:00
}
written = out - > written ;
if ( out - > conv ) {
xmlBufferFree ( out - > conv ) ;
2003-10-08 19:19:10 +00:00
out - > conv = NULL ;
2001-02-23 17:55:21 +00:00
}
if ( out - > encoder ! = NULL ) {
xmlCharEncCloseFunc ( out - > encoder ) ;
}
if ( out - > buffer ! = NULL ) {
xmlBufferFree ( out - > buffer ) ;
2003-10-08 19:19:10 +00:00
out - > buffer = NULL ;
2001-02-23 17:55:21 +00:00
}
2003-10-08 19:19:10 +00:00
if ( out - > error )
err_rc = - 1 ;
2001-02-23 17:55:21 +00:00
xmlFree ( out ) ;
2003-10-08 19:19:10 +00:00
return ( ( err_rc = = 0 ) ? written : err_rc ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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
2003-04-18 12:34:58 +00:00
xmlParserInputBufferCreateFilename ( const char * URI , xmlCharEncoding enc ) {
2001-02-23 17:55:21 +00:00
xmlParserInputBufferPtr ret ;
2001-07-08 18:35:48 +00:00
int i = 0 ;
2001-02-23 17:55:21 +00:00
void * context = NULL ;
if ( xmlInputCallbackInitialized = = 0 )
xmlRegisterDefaultInputCallbacks ( ) ;
if ( URI = = NULL ) return ( NULL ) ;
/*
2001-12-31 16:16:02 +00:00
* Try to find one of the input accept method accepting that scheme
2001-02-23 17:55:21 +00:00
* Go in reverse to give precedence to user defined handlers .
2001-07-08 18:35:48 +00:00
*/
if ( context = = NULL ) {
for ( i = xmlInputCallbackNr - 1 ; i > = 0 ; i - - ) {
if ( ( xmlInputCallbackTable [ i ] . matchcallback ! = NULL ) & &
( xmlInputCallbackTable [ i ] . matchcallback ( URI ) ! = 0 ) ) {
2003-02-19 14:51:00 +00:00
context = xmlInputCallbackTable [ i ] . opencallback ( URI ) ;
2003-10-18 11:29:40 +00:00
if ( context ! = NULL ) {
2001-07-08 18:35:48 +00:00
break ;
2003-10-18 11:29:40 +00:00
}
2001-07-08 18:35:48 +00:00
}
2001-02-23 17:55:21 +00:00
}
}
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 ;
2003-09-08 01:57:30 +00:00
# ifdef HAVE_ZLIB_H
2003-10-29 22:15:13 +00:00
if ( ( xmlInputCallbackTable [ i ] . opencallback = = xmlGzfileOpen ) & &
( strcmp ( URI , " - " ) ! = 0 ) ) {
2003-09-08 01:57:30 +00:00
if ( ( ( z_stream * ) context ) - > avail_in > 4 ) {
char * cptr , buff4 [ 4 ] ;
2003-09-10 10:51:05 +00:00
cptr = ( char * ) ( ( z_stream * ) context ) - > next_in ;
2003-09-08 01:57:30 +00:00
if ( gzread ( context , buff4 , 4 ) = = 4 ) {
if ( strncmp ( buff4 , cptr , 4 ) = = 0 )
ret - > compressed = 0 ;
else
ret - > compressed = 1 ;
gzrewind ( context ) ;
}
}
}
# endif
2001-02-23 17:55:21 +00:00
}
return ( ret ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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 ,
2003-09-29 13:20:24 +00:00
int compression ATTRIBUTE_UNUSED ) {
2001-02-23 17:55:21 +00:00
xmlOutputBufferPtr ret ;
2001-08-15 08:47:42 +00:00
int i = 0 ;
2001-02-23 17:55:21 +00:00
void * context = NULL ;
2001-08-15 08:47:42 +00:00
char * unescaped ;
2001-02-23 17:55:21 +00:00
2001-07-23 19:10:52 +00:00
int is_http_uri = 0 ; /* Can't change if HTTP disabled */
2001-02-23 17:55:21 +00:00
if ( xmlOutputCallbackInitialized = = 0 )
xmlRegisterDefaultOutputCallbacks ( ) ;
if ( URI = = NULL ) return ( NULL ) ;
2001-07-23 19:10:52 +00:00
# ifdef LIBXML_HTTP_ENABLED
/* Need to prevent HTTP URI's from falling into zlib short circuit */
2003-02-19 14:51:00 +00:00
is_http_uri = xmlIOHTTPMatch ( URI ) ;
2001-07-23 19:10:52 +00:00
# endif
2001-08-15 08:47:42 +00:00
/*
2001-12-31 16:16:02 +00:00
* Try to find one of the output accept method accepting that scheme
2001-08-15 08:47:42 +00:00
* Go in reverse to give precedence to user defined handlers .
* try with an unescaped version of the URI
*/
2003-02-19 14:51:00 +00:00
unescaped = xmlURIUnescapeString ( URI , 0 , NULL ) ;
2001-08-15 08:47:42 +00:00
if ( unescaped ! = NULL ) {
2001-02-23 17:55:21 +00:00
# ifdef HAVE_ZLIB_H
2001-08-15 08:47:42 +00:00
if ( ( compression > 0 ) & & ( compression < = 9 ) & & ( is_http_uri = = 0 ) ) {
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 ) ;
2001-02-23 17:55:21 +00:00
}
}
# endif
2001-08-15 08:47:42 +00:00
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 ) ;
}
2001-02-23 17:55:21 +00:00
/*
2001-08-15 08:47:42 +00:00
* If this failed try with a non - escaped URI this may be a strange
* filename
2001-02-23 17:55:21 +00:00
*/
2001-08-15 08:47:42 +00:00
if ( context = = NULL ) {
# ifdef HAVE_ZLIB_H
if ( ( compression > 0 ) & & ( compression < = 9 ) & & ( is_http_uri = = 0 ) ) {
2003-02-19 14:51:00 +00:00
context = xmlGzfileOpenW ( URI , compression ) ;
2001-08-15 08:47:42 +00:00
if ( context ! = NULL ) {
ret = xmlAllocOutputBuffer ( encoder ) ;
if ( ret ! = NULL ) {
ret - > context = context ;
ret - > writecallback = xmlGzfileWrite ;
ret - > closecallback = xmlGzfileClose ;
}
return ( ret ) ;
}
}
2001-07-23 19:10:52 +00:00
# endif
2001-08-15 08:47:42 +00:00
for ( i = xmlOutputCallbackNr - 1 ; i > = 0 ; i - - ) {
if ( ( xmlOutputCallbackTable [ i ] . matchcallback ! = NULL ) & &
2003-02-19 14:51:00 +00:00
( xmlOutputCallbackTable [ i ] . matchcallback ( URI ) ! = 0 ) ) {
2001-08-15 08:47:42 +00:00
# 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 ;
}
2001-02-23 17:55:21 +00:00
}
}
2001-07-23 19:10:52 +00:00
2001-02-23 17:55:21 +00:00
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 ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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 ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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 ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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 ) {
2001-07-17 20:07:33 +00:00
ret - > context = ( void * ) ( long ) fd ;
2001-02-23 17:55:21 +00:00
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 ;
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 ;
xmlBufferAdd ( ret - > buffer , ( const xmlChar * ) mem , size ) ;
}
return ( ret ) ;
}
2003-09-18 13:35:51 +00:00
/**
* 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 ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " creating input buffer " ) ;
2003-09-18 13:35:51 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , ( size_t ) sizeof ( xmlParserInputBuffer ) ) ;
2003-09-19 12:44:05 +00:00
ret - > buffer = xmlBufferCreateStatic ( ( void * ) mem , ( size_t ) size ) ;
2003-09-18 13:35:51 +00:00
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 ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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 ) {
2001-07-17 20:07:33 +00:00
ret - > context = ( void * ) ( long ) fd ;
2001-02-23 17:55:21 +00:00
ret - > writecallback = xmlFdWrite ;
2002-02-07 16:39:11 +00:00
ret - > closecallback = NULL ;
2001-02-23 17:55:21 +00:00
}
return ( ret ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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 ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* xmlOutputBufferCreateIO :
* @ iowrite : an I / O write function
* @ ioclose : an I / O close function
* @ ioctx : an I / O handler
2002-01-22 18:15:52 +00:00
* @ encoder : the charset encoding if known
2001-02-23 17:55:21 +00:00
*
* 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 ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
/**
* 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 ;
if ( len < 0 ) return ( 0 ) ;
2003-10-08 18:58:28 +00:00
if ( ( in = = NULL ) | | ( in - > error ) ) return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
if ( in - > encoder ! = NULL ) {
2004-02-11 13:25:26 +00:00
unsigned int use ;
2001-02-23 17:55:21 +00:00
/*
* Store the data in the incoming raw buffer
*/
if ( in - > raw = = NULL ) {
in - > raw = xmlBufferCreate ( ) ;
}
xmlBufferAdd ( in - > raw , ( const xmlChar * ) buf , len ) ;
/*
* convert as much as possible to the parser reading buffer .
*/
2004-02-11 13:25:26 +00:00
use = in - > raw - > use ;
2001-02-23 17:55:21 +00:00
nbchars = xmlCharEncInFunc ( in - > encoder , in - > buffer , in - > raw ) ;
if ( nbchars < 0 ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 18:58:28 +00:00
in - > error = XML_IO_ENCODER ;
2001-02-23 17:55:21 +00:00
return ( - 1 ) ;
}
2004-02-11 13:25:26 +00:00
in - > rawconsumed + = ( use - in - > raw - > use ) ;
2001-02-23 17:55:21 +00:00
} else {
nbchars = len ;
xmlBufferAdd ( in - > buffer , ( xmlChar * ) buf , nbchars ) ;
}
# ifdef DEBUG_INPUT
xmlGenericError ( xmlGenericErrorContext ,
" I/O: pushed %d chars, buffer %d/%d \n " ,
nbchars , in - > buffer - > use , in - > buffer - > size ) ;
# endif
return ( nbchars ) ;
}
2002-03-05 20:28:20 +00:00
/**
* 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 ) ;
}
2001-02-23 17:55:21 +00:00
/**
* 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
*
2001-12-31 16:16:02 +00:00
* TODO : one should be able to remove one extra copy by copying directly
2001-02-23 17:55:21 +00:00
* 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 ;
2002-06-10 15:59:44 +00:00
unsigned int needSize ;
2001-02-23 17:55:21 +00:00
2003-10-08 18:58:28 +00:00
if ( ( in = = NULL ) | | ( in - > error ) ) return ( - 1 ) ;
2003-08-19 15:01:28 +00:00
if ( ( len < = MINLEN ) & & ( len ! = 4 ) )
2001-02-23 17:55:21 +00:00
len = MINLEN ;
2003-08-19 15:01:28 +00:00
2001-02-23 17:55:21 +00:00
buffree = in - > buffer - > size - in - > buffer - > use ;
if ( buffree < = 0 ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_BUFFER_FULL , NULL ) ;
2003-10-08 18:58:28 +00:00
in - > error = XML_IO_BUFFER_FULL ;
2001-02-23 17:55:21 +00:00
return ( 0 ) ;
}
2002-05-16 08:43:22 +00:00
needSize = in - > buffer - > use + len + 1 ;
if ( needSize > in - > buffer - > size ) {
if ( ! xmlBufferResize ( in - > buffer , needSize ) ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " growing input buffer " ) ;
2003-10-08 18:58:28 +00:00
in - > error = XML_ERR_NO_MEMORY ;
2002-05-16 08:43:22 +00:00
return ( 0 ) ;
}
2001-02-23 17:55:21 +00:00
}
2002-05-16 08:43:22 +00:00
buffer = ( char * ) & in - > buffer - > content [ in - > buffer - > use ] ;
2001-02-23 17:55:21 +00:00
/*
* Call the read method for this I / O type .
*/
if ( in - > readcallback ! = NULL ) {
res = in - > readcallback ( in - > context , & buffer [ 0 ] , len ) ;
2002-03-05 20:28:20 +00:00
if ( res < = 0 )
in - > readcallback = endOfInput ;
2001-02-23 17:55:21 +00:00
} else {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_NO_INPUT , NULL ) ;
2003-10-08 18:58:28 +00:00
in - > error = XML_IO_NO_INPUT ;
2001-02-23 17:55:21 +00:00
return ( - 1 ) ;
}
if ( res < 0 ) {
return ( - 1 ) ;
}
len = res ;
if ( in - > encoder ! = NULL ) {
2004-02-11 13:25:26 +00:00
unsigned int use ;
2001-02-23 17:55:21 +00:00
/*
* Store the data in the incoming raw buffer
*/
if ( in - > raw = = NULL ) {
in - > raw = xmlBufferCreate ( ) ;
}
xmlBufferAdd ( in - > raw , ( const xmlChar * ) buffer , len ) ;
/*
* convert as much as possible to the parser reading buffer .
*/
2004-02-11 13:25:26 +00:00
use = in - > raw - > use ;
2001-02-23 17:55:21 +00:00
nbchars = xmlCharEncInFunc ( in - > encoder , in - > buffer , in - > raw ) ;
if ( nbchars < 0 ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 18:58:28 +00:00
in - > error = XML_IO_ENCODER ;
2001-02-23 17:55:21 +00:00
return ( - 1 ) ;
}
2004-02-11 13:25:26 +00:00
in - > rawconsumed + = ( use - in - > raw - > use ) ;
2001-02-23 17:55:21 +00:00
} else {
nbchars = len ;
2002-05-16 08:43:22 +00:00
in - > buffer - > use + = nbchars ;
buffer [ nbchars ] = 0 ;
2001-02-23 17:55:21 +00:00
}
# 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 ) {
2003-10-08 18:58:28 +00:00
if ( ( in = = NULL ) | | ( in - > error ) ) return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
if ( in - > readcallback ! = NULL )
return ( xmlParserInputBufferGrow ( in , len ) ) ;
2003-09-18 13:35:51 +00:00
else if ( ( in - > buffer ! = NULL ) & &
( in - > buffer - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) )
return ( 0 ) ;
2001-02-23 17:55:21 +00:00
else
return ( - 1 ) ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 17:55:21 +00:00
/**
* 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 */
2003-10-08 18:58:28 +00:00
if ( ( out = = NULL ) | | ( out - > error ) ) return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
if ( len < 0 ) return ( 0 ) ;
2003-10-08 18:58:28 +00:00
if ( out - > error ) return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
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 ( ) ;
}
xmlBufferAdd ( out - > buffer , ( const xmlChar * ) buf , chunk ) ;
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 ) ;
2003-02-10 15:43:53 +00:00
if ( ( ret < 0 ) & & ( ret ! = - 3 ) ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 18:58:28 +00:00
out - > error = XML_IO_ENCODER ;
2001-02-23 17:55:21 +00:00
return ( - 1 ) ;
}
nbchars = out - > conv - > use ;
} else {
xmlBufferAdd ( out - > buffer , ( const xmlChar * ) buf , chunk ) ;
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 )
2001-05-02 10:58:52 +00:00
xmlBufferShrink ( out - > conv , ret ) ;
2001-02-23 17:55:21 +00:00
} else {
ret = out - > writecallback ( out - > context ,
( const char * ) out - > buffer - > content , nbchars ) ;
if ( ret > = 0 )
2001-05-02 10:58:52 +00:00
xmlBufferShrink ( out - > buffer , ret ) ;
2001-02-23 17:55:21 +00:00
}
if ( ret < 0 ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_WRITE , NULL ) ;
2003-10-08 18:58:28 +00:00
out - > error = XML_IO_WRITE ;
2001-02-23 17:55:21 +00:00
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 ) ;
}
/**
* 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 ;
2003-10-08 18:58:28 +00:00
if ( ( out = = NULL ) | | ( out - > error ) ) return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
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 ;
2003-10-08 18:58:28 +00:00
if ( ( out = = NULL ) | | ( out - > error ) ) return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
/*
* 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 ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 18:58:28 +00:00
out - > error = XML_IO_ENCODER ;
2001-02-23 17:55:21 +00:00
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 ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_FLUSH , NULL ) ;
2003-10-08 18:58:28 +00:00
out - > error = XML_IO_FLUSH ;
2001-02-23 17:55:21 +00:00
return ( ret ) ;
}
out - > written + = ret ;
# ifdef DEBUG_INPUT
xmlGenericError ( xmlGenericErrorContext ,
" I/O: flushed %d chars \n " , ret ) ;
# endif
return ( ret ) ;
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 17:55:21 +00:00
2001-07-18 19:30:27 +00:00
/**
2001-02-23 17:55:21 +00:00
* 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 = ' / ' ;
2002-09-29 17:51:06 +00:00
# ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */
return NULL ;
# endif
2001-02-23 17:55:21 +00:00
if ( xmlInputCallbackInitialized = = 0 )
xmlRegisterDefaultInputCallbacks ( ) ;
if ( filename = = NULL ) return ( NULL ) ;
2002-01-08 10:36:16 +00:00
# if defined(WIN32) && !defined(__CYGWIN__)
2001-02-23 17:55:21 +00:00
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 *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-19 13:35:37 +00:00
/**
* 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 )
2003-10-27 11:25:13 +00:00
__xmlLoaderErr ( ctxt , " failed to load HTTP resource \" %s \" \n " ,
2003-10-19 13:35:37 +00:00
( const char * ) ret - > filename ) ;
else
2003-10-27 11:25:13 +00:00
__xmlLoaderErr ( ctxt , " failed to load HTTP resource \n " , NULL ) ;
2003-10-19 13:35:37 +00:00
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 ) ;
}
2002-03-20 21:55:57 +00:00
static int xmlSysIDExists ( const char * URL ) {
2001-08-23 21:17:48 +00:00
# ifdef HAVE_STAT
int ret ;
struct stat info ;
const char * path ;
if ( URL = = NULL )
return ( 0 ) ;
2002-09-10 11:13:43 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST URL , BAD_CAST " file://localhost/ " , 17 ) )
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2002-09-10 11:13:43 +00:00
path = & URL [ 17 ] ;
# else
2001-08-23 21:17:48 +00:00
path = & URL [ 16 ] ;
2002-09-10 11:13:43 +00:00
# endif
2002-05-01 18:32:28 +00:00
else if ( ! xmlStrncasecmp ( BAD_CAST URL , BAD_CAST " file:/// " , 8 ) ) {
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2001-08-23 21:17:48 +00:00
path = & URL [ 8 ] ;
# else
path = & URL [ 7 ] ;
# endif
} else
path = URL ;
ret = stat ( path , & info ) ;
2002-03-20 21:55:57 +00:00
if ( ret = = 0 )
return ( 1 ) ;
2001-08-23 21:17:48 +00:00
# endif
2002-03-20 21:55:57 +00:00
return ( 0 ) ;
2001-08-23 21:17:48 +00:00
}
2001-07-18 19:30:27 +00:00
/**
2001-02-23 17:55:21 +00:00
* 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 .
*/
2003-10-19 13:35:37 +00:00
static xmlParserInputPtr
2001-02-23 17:55:21 +00:00
xmlDefaultExternalEntityLoader ( const char * URL , const char * ID ,
2003-10-19 13:35:37 +00:00
xmlParserCtxtPtr ctxt )
{
2001-02-23 17:55:21 +00:00
xmlParserInputPtr ret = NULL ;
2001-08-22 00:06:49 +00:00
xmlChar * resource = NULL ;
2003-10-19 13:35:37 +00:00
2001-08-22 00:06:49 +00:00
# ifdef LIBXML_CATALOG_ENABLED
2001-08-22 14:29:45 +00:00
xmlCatalogAllow pref ;
2001-08-22 00:06:49 +00:00
# endif
2001-02-23 17:55:21 +00:00
# ifdef DEBUG_EXTERNAL_ENTITIES
xmlGenericError ( xmlGenericErrorContext ,
2003-10-19 13:35:37 +00:00
" xmlDefaultExternalEntityLoader(%s, xxx) \n " , URL ) ;
2001-02-23 17:55:21 +00:00
# endif
2001-05-10 15:34:11 +00:00
# ifdef LIBXML_CATALOG_ENABLED
2003-11-03 14:28:31 +00:00
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 ) ;
}
2001-05-10 15:34:11 +00:00
/*
2001-08-22 00:06:49 +00:00
* If the resource doesn ' t exists as a file ,
2001-08-22 16:30:37 +00:00
* try to load it from the resource pointed in the catalogs
2001-05-10 15:34:11 +00:00
*/
2001-08-22 14:29:45 +00:00
pref = xmlCatalogGetDefaults ( ) ;
2002-03-20 21:55:57 +00:00
if ( ( pref ! = XML_CATA_ALLOW_NONE ) & & ( ! xmlSysIDExists ( URL ) ) ) {
2003-10-19 13:35:37 +00:00
/*
* Do a local lookup
*/
if ( ( ctxt - > catalogs ! = NULL ) & &
( ( pref = = XML_CATA_ALLOW_ALL ) | |
( pref = = XML_CATA_ALLOW_DOCUMENT ) ) ) {
resource = xmlCatalogLocalResolve ( ctxt - > catalogs ,
( const xmlChar * ) ID ,
( const xmlChar * ) URL ) ;
2001-08-22 14:29:45 +00:00
}
2003-10-19 13:35:37 +00:00
/*
* 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 ) ;
2001-08-22 16:30:37 +00:00
2003-10-19 13:35:37 +00:00
/*
* TODO : do an URI lookup on the reference
*/
if ( ( resource ! = NULL )
& & ( ! xmlSysIDExists ( ( const char * ) resource ) ) ) {
xmlChar * tmp = NULL ;
if ( ( 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 ) ;
}
2001-08-22 16:30:37 +00:00
2003-10-19 13:35:37 +00:00
if ( tmp ! = NULL ) {
xmlFree ( resource ) ;
resource = tmp ;
}
}
2001-08-22 14:29:45 +00:00
}
2001-05-10 15:34:11 +00:00
# endif
if ( resource = = NULL )
2003-10-19 13:35:37 +00:00
resource = ( xmlChar * ) URL ;
2001-05-10 15:34:11 +00:00
if ( resource = = NULL ) {
2003-10-19 13:35:37 +00:00
if ( ID = = NULL )
ID = " NULL " ;
2003-10-27 11:25:13 +00:00
__xmlLoaderErr ( ctxt , " failed to load external entity \" %s \" \n " , ID ) ;
2003-10-19 13:35:37 +00:00
return ( NULL ) ;
2001-02-23 17:55:21 +00:00
}
2003-10-19 13:35:37 +00:00
ret = xmlNewInputFromFile ( ctxt , ( const char * ) resource ) ;
2001-08-22 16:30:37 +00:00
if ( ( resource ! = NULL ) & & ( resource ! = ( xmlChar * ) URL ) )
2003-10-19 13:35:37 +00:00
xmlFree ( resource ) ;
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
xmlDefaultExternalEntityLoader ;
2001-07-18 19:30:27 +00:00
/**
2001-02-23 17:55:21 +00:00
* xmlSetExternalEntityLoader :
* @ f : the new entity resolver function
*
* Changes the defaultexternal entity resolver function for the application
*/
void
xmlSetExternalEntityLoader ( xmlExternalEntityLoader f ) {
xmlCurrentExternalEntityLoader = f ;
}
2001-07-18 19:30:27 +00:00
/**
2001-02-23 17:55:21 +00:00
* xmlGetExternalEntityLoader :
*
* Get the default external entity resolver function for the application
*
* Returns the xmlExternalEntityLoader function pointer
*/
xmlExternalEntityLoader
xmlGetExternalEntityLoader ( void ) {
return ( xmlCurrentExternalEntityLoader ) ;
}
2001-07-18 19:30:27 +00:00
/**
2001-02-23 17:55:21 +00:00
* xmlLoadExternalEntity :
* @ URL : the URL for the entity to load
2001-08-23 15:31:19 +00:00
* @ ID : the Public ID for the entity to load
2001-02-23 17:55:21 +00:00
* @ 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
2001-12-31 16:16:02 +00:00
* TODO : a more generic External entity API must be designed
2001-02-23 17:55:21 +00:00
*
* Returns the xmlParserInputPtr or NULL
*/
xmlParserInputPtr
xmlLoadExternalEntity ( const char * URL , const char * ID ,
xmlParserCtxtPtr ctxt ) {
2003-06-09 10:30:33 +00:00
if ( ( URL ! = NULL ) & & ( xmlSysIDExists ( URL ) = = 0 ) ) {
char * canonicFilename ;
xmlParserInputPtr ret ;
canonicFilename = ( char * ) xmlCanonicPath ( ( const xmlChar * ) URL ) ;
if ( canonicFilename = = NULL ) {
2003-10-08 11:54:57 +00:00
xmlIOErrMemory ( " building canonical path \n " ) ;
2003-06-09 10:30:33 +00:00
return ( NULL ) ;
}
ret = xmlCurrentExternalEntityLoader ( canonicFilename , ID , ctxt ) ;
xmlFree ( canonicFilename ) ;
return ( ret ) ;
}
2001-02-23 17:55:21 +00:00
return ( xmlCurrentExternalEntityLoader ( URL , ID , ctxt ) ) ;
}
2001-10-31 17:52:43 +00:00
/************************************************************************
* *
* 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 ) ;
2002-09-10 11:13:43 +00:00
if ( ! xmlStrncasecmp ( BAD_CAST URL , BAD_CAST " file://localhost/ " , 17 ) )
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2002-09-10 11:13:43 +00:00
path = & URL [ 17 ] ;
# else
path = & URL [ 16 ] ;
# endif
2002-05-01 18:32:28 +00:00
else if ( ! xmlStrncasecmp ( BAD_CAST URL , BAD_CAST " file:/// " , 8 ) ) {
2003-07-05 20:43:43 +00:00
# if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__)
2001-10-31 17:52:43 +00:00
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 - > 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 - > 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 ) {
2002-05-01 18:32:28 +00:00
if ( ( ! xmlStrncasecmp ( BAD_CAST resource , BAD_CAST " ftp:// " , 6 ) ) | |
( ! xmlStrncasecmp ( BAD_CAST resource , BAD_CAST " http:// " , 7 ) ) ) {
2003-10-08 11:54:57 +00:00
xmlIOErr ( XML_IO_NETWORK_ATTEMPT , ( const char * ) resource ) ;
2001-10-31 17:52:43 +00:00
if ( resource ! = ( xmlChar * ) URL )
xmlFree ( resource ) ;
return ( NULL ) ;
}
}
input = xmlDefaultExternalEntityLoader ( ( const char * ) resource , ID , ctxt ) ;
if ( resource ! = ( xmlChar * ) URL )
xmlFree ( resource ) ;
return ( input ) ;
}