2001-02-23 20:55:21 +03:00
/*
* xmlIO . c : implementation of the I / O interfaces used by the parser
*
* See Copyright for the status of this software .
*
2001-08-20 04:08:40 +04:00
* daniel @ veillard . com
2001-02-23 20:55:21 +03:00
*
* 14 Nov 2000 ht - for VMS , truncated name of long functions to under 32 char
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# include <string.h>
2022-03-02 02:29:17 +03:00
# include <stdlib.h>
2001-02-23 20:55:21 +03:00
# include <errno.h>
# 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
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-02-23 20:55:21 +03:00
# include <zlib.h>
# endif
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_LZMA_ENABLED
2011-09-18 18:59:13 +04:00
# include <lzma.h>
# endif
2001-02-23 20:55:21 +03:00
2022-03-01 00:42:10 +03:00
# if defined(_WIN32)
2017-10-09 01:20:01 +03:00
# define WIN32_LEAN_AND_MEAN
2006-04-27 12:15:20 +04:00
# include <windows.h>
2022-03-30 02:07:51 +03:00
# include <io.h>
# include <direct.h>
2006-04-27 12:15:20 +04:00
# endif
2017-10-09 16:35:32 +03:00
# ifndef S_ISDIR
# ifdef _S_ISDIR
# define S_ISDIR(x) _S_ISDIR(x)
# elif defined(S_IFDIR)
# ifdef S_IFMT
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
# elif defined(_S_IFMT)
# define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
2001-02-23 20:55:21 +03:00
# endif
# endif
# endif
# include <libxml/xmlmemory.h>
# include <libxml/parser.h>
# include <libxml/parserInternals.h>
# include <libxml/xmlIO.h>
2001-07-08 22:35:48 +04:00
# include <libxml/uri.h>
2001-02-23 20:55:21 +03:00
# include <libxml/nanohttp.h>
# include <libxml/nanoftp.h>
# include <libxml/xmlerror.h>
2001-05-10 19:34:11 +04:00
# ifdef LIBXML_CATALOG_ENABLED
# include <libxml/catalog.h>
# endif
2001-10-17 19:58:35 +04:00
# include <libxml/globals.h>
2001-02-23 20:55:21 +03:00
2022-08-26 02:22:33 +03:00
# include "private/buf.h"
# include "private/enc.h"
# include "private/error.h"
# include "private/io.h"
# include "private/parser.h"
2012-07-16 10:22:54 +04:00
2001-07-23 23:10:52 +04:00
/* #define VERBOSE_FAILURE */
2001-07-05 02:54:28 +04:00
/* #define DEBUG_EXTERNAL_ENTITIES */
2001-02-23 20:55:21 +03: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 04:06:07 +04:00
static xmlInputCallback xmlInputCallbackTable [ MAX_INPUT_CALLBACK ] ;
static int xmlInputCallbackNr = 0 ;
static int xmlInputCallbackInitialized = 0 ;
2001-02-23 20:55:21 +03:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 04:06:07 +04:00
static xmlOutputCallback xmlOutputCallbackTable [ MAX_OUTPUT_CALLBACK ] ;
static int xmlOutputCallbackNr = 0 ;
static int xmlOutputCallbackInitialized = 0 ;
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
2003-10-08 15:54:57 +04:00
/************************************************************************
* *
2009-08-11 19:51:22 +04:00
* Tree memory error handler *
2003-10-08 15:54:57 +04:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-21 01:21:43 +03:00
static const char * const IOerr [ ] = {
2003-10-08 23:26:03 +04:00
" Unknown IO error " , /* UNKNOWN */
2003-10-08 15:54:57 +04: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 23:36:36 +04:00
" Attempt to load network entity %s " , /* XML_IO_NETWORK_ATTEMPT */
2003-10-08 15:54:57 +04:00
" encoder error " , /* XML_IO_ENCODER */
2003-10-10 23:36:36 +04:00
" flush error " ,
" write error " ,
" no input " ,
" buffer full " ,
" loading error " ,
" not a socket " , /* ENOTSOCK */
" already connected " , /* EISCONN */
2004-08-16 04:39:03 +04:00
" connection refused " , /* ECONNREFUSED */
2003-10-10 23:36:36 +04:00
" unreachable network " , /* ENETUNREACH */
2019-09-30 18:04:54 +03:00
" address in use " , /* EADDRINUSE */
2003-10-10 23:36:36 +04:00
" already in use " , /* EALREADY */
2019-09-30 18:04:54 +03:00
" unknown address family " , /* EAFNOSUPPORT */
2003-10-08 15:54:57 +04:00
} ;
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2006-04-27 12:15:20 +04:00
/**
* __xmlIOWin32UTF8ToWChar :
* @ u8String : uft - 8 string
*
* Convert a string from utf - 8 to wchar ( WINDOWS ONLY ! )
*/
static wchar_t *
__xmlIOWin32UTF8ToWChar ( const char * u8String )
{
2006-10-11 20:43:06 +04:00
wchar_t * wString = NULL ;
if ( u8String ) {
int wLen =
MultiByteToWideChar ( CP_UTF8 , MB_ERR_INVALID_CHARS , u8String ,
- 1 , NULL , 0 ) ;
if ( wLen ) {
wString = xmlMalloc ( wLen * sizeof ( wchar_t ) ) ;
if ( wString ) {
if ( MultiByteToWideChar
( CP_UTF8 , 0 , u8String , - 1 , wString , wLen ) = = 0 ) {
xmlFree ( wString ) ;
wString = NULL ;
}
}
}
}
2006-04-27 12:15:20 +04:00
2006-10-11 20:43:06 +04:00
return wString ;
2006-04-27 12:15:20 +04:00
}
# endif
2003-10-08 15:54:57 +04:00
/**
* xmlIOErrMemory :
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2003-10-08 15:54:57 +04:00
*
* 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 23:36:36 +04:00
* __xmlIOErr :
2003-10-08 15:54:57 +04:00
* @ code : the error number
2003-10-10 23:36:36 +04:00
* @
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2003-10-08 15:54:57 +04:00
*
2003-10-09 02:38:13 +04:00
* Handle an I / O error
2003-10-08 15:54:57 +04:00
*/
2003-10-10 23:36:36 +04:00
void
__xmlIOErr ( int domain , int code , const char * extra )
2003-10-08 15:54:57 +04:00
{
unsigned int idx ;
if ( code = = 0 ) {
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 23:36:36 +04: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 15:54:57 +04:00
# endif
else code = XML_IO_UNKNOWN ;
}
idx = 0 ;
if ( code > = XML_IO_UNKNOWN ) idx = code - XML_IO_UNKNOWN ;
if ( idx > = ( sizeof ( IOerr ) / sizeof ( IOerr [ 0 ] ) ) ) idx = 0 ;
2009-08-11 19:51:22 +04:00
2003-10-10 23:36:36 +04:00
__xmlSimpleError ( domain , code , NULL , IOerr [ idx ] , extra ) ;
}
/**
* xmlIOErr :
* @ code : the error number
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2003-10-10 23:36:36 +04:00
*
* Handle an I / O error
*/
static void
xmlIOErr ( int code , const char * extra )
{
__xmlIOErr ( XML_FROM_IO , code , extra ) ;
2003-10-08 15:54:57 +04:00
}
2002-09-10 15:13:43 +04:00
2003-10-09 02:38:13 +04:00
/**
2003-10-27 14:25:13 +03:00
* __xmlLoaderErr :
* @ ctx : the parser context
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2003-10-09 02:38:13 +04:00
*
* Handle a resource access error
*/
2003-10-27 14:25:13 +03:00
void
__xmlLoaderErr ( void * ctx , const char * msg , const char * filename )
2003-10-09 02:38:13 +04:00
{
2003-10-27 14:25:13 +03:00
xmlParserCtxtPtr ctxt = ( xmlParserCtxtPtr ) ctx ;
2003-10-10 18:10:40 +04:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-09 02:38:13 +04:00
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
xmlErrorLevel level = XML_ERR_ERROR ;
2003-10-31 13:36:03 +03:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > disableSAX ! = 0 ) & &
( ctxt - > instate = = XML_PARSER_EOF ) )
return ;
2003-10-09 02:38:13 +04: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 ;
}
2004-11-08 14:54:28 +03:00
if ( ctxt - > sax - > initialized = = XML_SAX2_MAGIC )
schannel = ctxt - > sax - > serror ;
2003-10-09 02:38:13 +04:00
data = ctxt - > userData ;
}
2003-10-10 18:10:40 +04:00
__xmlRaiseError ( schannel , channel , data , ctxt , NULL , XML_FROM_IO ,
2003-10-09 02:38:13 +04:00
XML_IO_LOAD_ERROR , level , NULL , 0 ,
filename , NULL , NULL , 0 , 0 ,
msg , filename ) ;
2009-08-11 19:51:22 +04:00
2003-10-09 02:38:13 +04:00
}
2003-10-08 15:54:57 +04:00
/************************************************************************
* *
2009-08-11 19:51:22 +04:00
* Tree memory error handler *
2003-10-08 15:54:57 +04:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-10 15:13:43 +04:00
/**
2002-12-10 18:19:08 +03:00
* xmlNormalizeWindowsPath :
2003-04-17 13:09:19 +04:00
* @ path : the input file path
2002-09-10 15:13:43 +04:00
*
2003-02-19 17:51:00 +03:00
* This function is obsolete . Please see xmlURIFromPath in uri . c for
* a better solution .
2003-04-17 13:09:19 +04:00
*
* Returns a canonicalized version of the path
2002-09-10 15:13:43 +04:00
*/
xmlChar *
xmlNormalizeWindowsPath ( const xmlChar * path )
{
2003-02-19 17:51:00 +03:00
return xmlCanonicPath ( path ) ;
2002-09-10 15:13:43 +04:00
}
2001-10-29 23:21:47 +03:00
/**
* xmlCleanupInputCallbacks :
*
* clears the entire input callback table . this includes the
2009-08-11 19:51:22 +04:00
* compiled - in I / O .
2001-10-29 23:21:47 +03:00
*/
void
xmlCleanupInputCallbacks ( void )
{
int i ;
if ( ! xmlInputCallbackInitialized )
return ;
2001-11-27 19:23:50 +03:00
for ( i = xmlInputCallbackNr - 1 ; i > = 0 ; i - - ) {
2001-10-29 23:21:47 +03:00
xmlInputCallbackTable [ i ] . matchcallback = NULL ;
xmlInputCallbackTable [ i ] . opencallback = NULL ;
xmlInputCallbackTable [ i ] . readcallback = NULL ;
xmlInputCallbackTable [ i ] . closecallback = NULL ;
}
xmlInputCallbackNr = 0 ;
2002-06-07 01:46:13 +04:00
xmlInputCallbackInitialized = 0 ;
2001-10-29 23:21:47 +03:00
}
2004-05-08 06:32:07 +04:00
/**
2004-08-04 02:41:11 +04:00
* xmlPopInputCallbacks :
2004-05-08 06:32:07 +04:00
*
* Clear the top input callback from the input stack . this includes the
2009-08-11 19:51:22 +04:00
* compiled - in I / O .
2004-05-08 06:32:07 +04:00
*
* Returns the number of input callback registered or - 1 in case of error .
*/
int
xmlPopInputCallbacks ( void )
{
if ( ! xmlInputCallbackInitialized )
return ( - 1 ) ;
if ( xmlInputCallbackNr < = 0 )
return ( - 1 ) ;
2009-08-11 19:51:22 +04:00
2004-05-08 06:32:07 +04:00
xmlInputCallbackNr - - ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . matchcallback = NULL ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . opencallback = NULL ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . readcallback = NULL ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . closecallback = NULL ;
return ( xmlInputCallbackNr ) ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-10-29 23:21:47 +03:00
/**
* xmlCleanupOutputCallbacks :
*
* clears the entire output callback table . this includes the
2009-08-11 19:51:22 +04:00
* compiled - in I / O callbacks .
2001-10-29 23:21:47 +03:00
*/
void
xmlCleanupOutputCallbacks ( void )
{
int i ;
if ( ! xmlOutputCallbackInitialized )
return ;
2001-11-27 19:23:50 +03:00
for ( i = xmlOutputCallbackNr - 1 ; i > = 0 ; i - - ) {
2001-10-29 23:21:47 +03:00
xmlOutputCallbackTable [ i ] . matchcallback = NULL ;
xmlOutputCallbackTable [ i ] . opencallback = NULL ;
xmlOutputCallbackTable [ i ] . writecallback = NULL ;
xmlOutputCallbackTable [ i ] . closecallback = NULL ;
}
xmlOutputCallbackNr = 0 ;
2002-06-07 01:46:13 +04:00
xmlOutputCallbackInitialized = 0 ;
2001-10-29 23:21:47 +03:00
}
2020-02-11 13:32:23 +03:00
/**
* xmlPopOutputCallbacks :
*
* Remove the top output callbacks from the output stack . This includes the
* compiled - in I / O .
*
* Returns the number of output callback registered or - 1 in case of error .
*/
int
xmlPopOutputCallbacks ( void )
{
if ( ! xmlOutputCallbackInitialized )
return ( - 1 ) ;
if ( xmlOutputCallbackNr < = 0 )
return ( - 1 ) ;
xmlOutputCallbackNr - - ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . matchcallback = NULL ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . opencallback = NULL ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . writecallback = NULL ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . closecallback = NULL ;
return ( xmlOutputCallbackNr ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-10-29 23:21:47 +03:00
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* Standard I / O for file accesses *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2006-09-01 13:56:07 +04:00
/**
* xmlWrapOpenUtf8 :
* @ path : the path in utf - 8 encoding
* @ mode : type of access ( 0 - read , 1 - write )
*
* function opens the file specified by @ path
*
*/
static FILE *
xmlWrapOpenUtf8 ( const char * path , int mode )
{
FILE * fd = NULL ;
wchar_t * wPath ;
wPath = __xmlIOWin32UTF8ToWChar ( path ) ;
if ( wPath )
{
fd = _wfopen ( wPath , mode ? L " wb " : L " rb " ) ;
xmlFree ( wPath ) ;
}
2006-10-10 13:05:36 +04:00
/* maybe path in native encoding */
2006-09-01 13:56:07 +04:00
if ( fd = = NULL )
fd = fopen ( path , mode ? " wb " : " rb " ) ;
return fd ;
}
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2009-08-11 19:51:22 +04:00
static gzFile
xmlWrapGzOpenUtf8 ( const char * path , const char * mode )
{
gzFile fd ;
wchar_t * wPath ;
fd = gzopen ( path , mode ) ;
if ( fd )
return fd ;
wPath = __xmlIOWin32UTF8ToWChar ( path ) ;
if ( wPath )
{
int d , m = ( strstr ( mode , " r " ) ? O_RDONLY : O_RDWR ) ;
# ifdef _O_BINARY
m | = ( strstr ( mode , " b " ) ? _O_BINARY : 0 ) ;
# endif
d = _wopen ( wPath , m ) ;
if ( d > = 0 )
fd = gzdopen ( d , mode ) ;
xmlFree ( wPath ) ;
}
return fd ;
}
2009-08-12 19:41:27 +04:00
# endif
2009-08-11 19:51:22 +04:00
2006-09-01 13:56:07 +04:00
/**
* xmlWrapStatUtf8 :
* @ path : the path in utf - 8 encoding
* @ info : structure that stores results
*
* function obtains information about the file or directory
*
*/
static int
2017-10-09 16:35:32 +03:00
xmlWrapStatUtf8 ( const char * path , struct _stat * info ) {
2006-09-01 13:56:07 +04:00
int retval = - 1 ;
wchar_t * wPath ;
wPath = __xmlIOWin32UTF8ToWChar ( path ) ;
2017-10-09 16:35:32 +03:00
if ( wPath ) {
retval = _wstat ( wPath , info ) ;
2006-09-01 13:56:07 +04:00
xmlFree ( wPath ) ;
}
2006-10-10 13:05:36 +04:00
/* maybe path in native encoding */
2006-09-01 13:56:07 +04:00
if ( retval < 0 )
2017-10-09 16:35:32 +03:00
retval = _stat ( path , info ) ;
2006-09-01 13:56:07 +04:00
return retval ;
}
# endif
2001-02-23 20:55:21 +03:00
/**
2002-12-11 17:23:49 +03:00
* xmlCheckFilename :
2001-02-23 20:55:21 +03: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 15:15:18 +04:00
* returns 2. otherwise returns 1.
2001-02-23 20:55:21 +03:00
*/
2002-10-14 15:15:18 +04:00
int
2001-02-23 20:55:21 +03:00
xmlCheckFilename ( const char * path )
{
2006-09-01 13:56:07 +04:00
# ifdef HAVE_STAT
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2017-10-09 16:35:32 +03:00
struct _stat stat_buffer ;
# else
2012-09-07 08:14:00 +04:00
struct stat stat_buffer ;
2017-10-09 16:35:32 +03:00
# endif
2006-05-03 00:34:38 +04:00
# endif
2012-09-07 08:14:00 +04:00
if ( path = = NULL )
return ( 0 ) ;
2006-08-30 17:11:36 +04:00
2001-02-23 20:55:21 +03:00
# ifdef HAVE_STAT
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2012-09-07 08:14:00 +04:00
/*
* On Windows stat and wstat do not work with long pathname ,
* which start with ' \ \ ? \ '
*/
if ( ( path [ 0 ] = = ' \\ ' ) & & ( path [ 1 ] = = ' \\ ' ) & & ( path [ 2 ] = = ' ? ' ) & &
( path [ 3 ] = = ' \\ ' ) )
return 1 ;
2017-10-09 16:35:32 +03:00
if ( xmlWrapStatUtf8 ( path , & stat_buffer ) = = - 1 )
2006-09-01 13:56:07 +04:00
return 0 ;
# else
2001-02-23 20:55:21 +03:00
if ( stat ( path , & stat_buffer ) = = - 1 )
return 0 ;
2006-09-01 13:56:07 +04:00
# endif
2002-10-14 15:15:18 +04:00
# ifdef S_ISDIR
2006-04-27 12:15:20 +04:00
if ( S_ISDIR ( stat_buffer . st_mode ) )
2002-10-14 15:15:18 +04:00
return 2 ;
2006-09-01 13:56:07 +04:00
# endif
2006-04-27 12:15:20 +04:00
# endif /* HAVE_STAT */
2001-02-23 20:55:21 +03:00
return 1 ;
}
/**
* 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 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlFdRead ( void * context , char * buffer , int len ) {
2003-10-08 15:54:57 +04:00
int ret ;
2017-10-09 14:37:42 +03:00
ret = read ( ( int ) ( ptrdiff_t ) context , & buffer [ 0 ] , len ) ;
2003-10-08 15:54:57 +04:00
if ( ret < 0 ) xmlIOErr ( 0 , " read() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlFdWrite ( void * context , const char * buffer , int len ) {
2005-10-28 18:54:17 +04:00
int ret = 0 ;
2003-10-08 15:54:57 +04:00
2005-10-28 18:54:17 +04:00
if ( len > 0 ) {
2017-10-09 14:37:42 +03:00
ret = write ( ( int ) ( ptrdiff_t ) context , & buffer [ 0 ] , len ) ;
2005-10-28 18:54:17 +04:00
if ( ret < 0 ) xmlIOErr ( 0 , " write() " ) ;
}
2003-10-08 15:54:57 +04:00
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlFdClose :
* @ context : the I / O context
*
* Close an I / O channel
2001-07-23 23:10:52 +04:00
*
* Returns 0 in case of success and error code otherwise
2001-02-23 20:55:21 +03:00
*/
2001-07-23 23:10:52 +04:00
static int
2001-02-23 20:55:21 +03:00
xmlFdClose ( void * context ) {
2003-10-08 15:54:57 +04:00
int ret ;
2017-10-09 14:37:42 +03:00
ret = close ( ( int ) ( ptrdiff_t ) context ) ;
2003-10-08 15:54:57 +04:00
if ( ret < 0 ) xmlIOErr ( 0 , " close() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlFileMatch :
* @ filename : the URI for matching
*
* input from FILE *
*
* Returns 1 if matches , 0 otherwise
*/
2002-05-01 22:32:28 +04:00
int
2001-03-26 20:28:29 +04:00
xmlFileMatch ( const char * filename ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
}
/**
2003-01-10 19:09:51 +03:00
* xmlFileOpen_real :
2001-02-23 20:55:21 +03: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 19:09:51 +03:00
static void *
xmlFileOpen_real ( const char * filename ) {
2014-07-26 17:14:53 +04:00
const char * path = filename ;
2006-09-01 13:56:07 +04:00
FILE * fd ;
2001-02-23 20:55:21 +03:00
2004-11-04 02:25:47 +03:00
if ( filename = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
if ( ! strcmp ( filename , " - " ) ) {
fd = stdin ;
return ( ( void * ) fd ) ;
}
2007-06-12 13:39:14 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) ) {
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2002-08-25 18:39:16 +04:00
path = & filename [ 17 ] ;
# else
2001-02-23 20:55:21 +03:00
path = & filename [ 16 ] ;
2002-08-25 18:39:16 +04:00
# endif
2007-06-12 13:39:14 +04:00
} else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2001-08-14 16:18:09 +04:00
path = & filename [ 8 ] ;
# else
2001-05-31 22:43:43 +04:00
path = & filename [ 7 ] ;
2007-06-12 13:39:14 +04:00
# endif
} else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/ " , 6 ) ) {
/* lots of generators seems to lazy to read RFC 1738 */
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2007-06-12 13:39:14 +04:00
path = & filename [ 6 ] ;
# else
path = & filename [ 5 ] ;
2001-08-14 16:18:09 +04:00
# endif
2014-07-26 17:14:53 +04:00
}
2001-02-23 20:55:21 +03:00
2017-08-28 15:30:43 +03:00
/* Do not check DDNAME on zOS ! */
# if !defined(__MVS__)
2001-02-23 20:55:21 +03:00
if ( ! xmlCheckFilename ( path ) )
return ( NULL ) ;
2017-08-28 15:30:43 +03:00
# endif
2001-02-23 20:55:21 +03:00
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2017-10-09 16:35:32 +03:00
fd = xmlWrapOpenUtf8 ( path , 0 ) ;
2006-09-01 13:56:07 +04:00
# else
2022-03-01 01:39:00 +03:00
fd = fopen ( path , " rb " ) ;
2001-02-23 20:55:21 +03:00
# endif /* WIN32 */
2006-09-01 13:56:07 +04:00
if ( fd = = NULL ) xmlIOErr ( 0 , path ) ;
2001-02-23 20:55:21 +03:00
return ( ( void * ) fd ) ;
}
2003-01-10 19:09:51 +03: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 16:19:53 +03:00
*
* Returns a handler or NULL in case or failure
2003-01-10 19:09:51 +03:00
*/
void *
xmlFileOpen ( const char * filename ) {
char * unescaped ;
void * retval ;
2004-11-04 02:25:47 +03:00
2007-03-30 16:39:25 +04:00
retval = xmlFileOpen_real ( filename ) ;
if ( retval = = NULL ) {
unescaped = xmlURIUnescapeString ( filename , 0 , NULL ) ;
if ( unescaped ! = NULL ) {
retval = xmlFileOpen_real ( unescaped ) ;
xmlFree ( unescaped ) ;
}
2003-01-10 19:09:51 +03:00
}
2007-03-30 16:39:25 +04:00
2003-01-10 19:09:51 +03:00
return retval ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
static void *
2001-02-23 20:55:21 +03:00
xmlFileOpenW ( const char * filename ) {
const char * path = NULL ;
2006-09-01 13:56:07 +04:00
FILE * fd ;
2001-02-23 20:55:21 +03:00
if ( ! strcmp ( filename , " - " ) ) {
fd = stdout ;
return ( ( void * ) fd ) ;
}
2002-09-10 15:13:43 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2002-09-10 15:13:43 +04:00
path = & filename [ 17 ] ;
# else
2001-02-23 20:55:21 +03:00
path = & filename [ 16 ] ;
2002-09-10 15:13:43 +04:00
# endif
2002-05-01 22:32:28 +04:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2001-08-14 16:18:09 +04:00
path = & filename [ 8 ] ;
# else
2001-05-31 22:43:43 +04:00
path = & filename [ 7 ] ;
2001-08-14 16:18:09 +04:00
# endif
2009-08-11 19:51:22 +04:00
} else
2001-02-23 20:55:21 +03:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2017-10-09 16:35:32 +03:00
fd = xmlWrapOpenUtf8 ( path , 1 ) ;
2017-08-28 15:30:43 +03:00
# elif(__MVS__)
fd = fopen ( path , " w " ) ;
2006-09-01 13:56:07 +04:00
# else
2017-08-28 15:30:43 +03:00
fd = fopen ( path , " wb " ) ;
2006-09-01 13:56:07 +04:00
# endif /* WIN32 */
2006-08-30 17:11:36 +04:00
2017-08-28 15:30:43 +03:00
if ( fd = = NULL ) xmlIOErr ( 0 , path ) ;
2001-02-23 20:55:21 +03:00
return ( ( void * ) fd ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03: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 .
*
2004-11-05 20:22:25 +03:00
* Returns the number of bytes written or < 0 in case of failure
2001-02-23 20:55:21 +03:00
*/
2002-05-01 22:32:28 +04:00
int
2001-02-23 20:55:21 +03:00
xmlFileRead ( void * context , char * buffer , int len ) {
2003-10-08 15:54:57 +04:00
int ret ;
2009-08-11 19:51:22 +04:00
if ( ( context = = NULL ) | | ( buffer = = NULL ) )
2004-11-05 20:22:25 +03:00
return ( - 1 ) ;
2003-10-08 15:54:57 +04:00
ret = fread ( & buffer [ 0 ] , 1 , len , ( FILE * ) context ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " fread() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlFileWrite ( void * context , const char * buffer , int len ) {
2002-12-17 21:33:01 +03:00
int items ;
2009-08-11 19:51:22 +04:00
if ( ( context = = NULL ) | | ( buffer = = NULL ) )
2004-11-05 20:22:25 +03:00
return ( - 1 ) ;
2002-12-17 21:33:01 +03:00
items = fwrite ( & buffer [ 0 ] , len , 1 , ( FILE * ) context ) ;
2003-10-08 22:58:28 +04:00
if ( ( items = = 0 ) & & ( ferror ( ( FILE * ) context ) ) ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( 0 , " fwrite() " ) ;
2003-10-08 22:58:28 +04:00
return ( - 1 ) ;
}
2002-12-17 21:33:01 +03:00
return ( items * len ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlFileClose :
* @ context : the I / O context
*
* Close an I / O channel
2002-12-11 17:23:49 +03:00
*
* Returns 0 or - 1 in case of error
2001-02-23 20:55:21 +03:00
*/
2002-05-01 22:32:28 +04:00
int
2001-02-23 20:55:21 +03:00
xmlFileClose ( void * context ) {
2001-10-30 13:32:36 +03:00
FILE * fil ;
2003-10-08 15:54:57 +04:00
int ret ;
2001-10-30 13:32:36 +03:00
2004-11-04 02:25:47 +03:00
if ( context = = NULL )
return ( - 1 ) ;
2001-10-30 13:32:36 +03:00
fil = ( FILE * ) context ;
2004-03-22 18:22:58 +03:00
if ( ( fil = = stdout ) | | ( fil = = stderr ) ) {
ret = fflush ( fil ) ;
if ( ret < 0 )
xmlIOErr ( 0 , " fflush() " ) ;
2001-10-30 13:32:36 +03:00
return ( 0 ) ;
2004-03-22 18:22:58 +03:00
}
if ( fil = = stdin )
2001-11-22 21:20:37 +03:00
return ( 0 ) ;
2003-10-08 15:54:57 +04:00
ret = ( fclose ( ( FILE * ) context ) = = EOF ) ? - 1 : 0 ;
if ( ret < 0 )
xmlIOErr ( 0 , " fclose() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlFileFlush :
* @ context : the I / O context
*
* Flush an I / O channel
*/
2001-07-23 23:10:52 +04:00
static int
2001-02-23 20:55:21 +03:00
xmlFileFlush ( void * context ) {
2003-10-08 15:54:57 +04:00
int ret ;
2004-11-04 02:25:47 +03:00
if ( context = = NULL )
return ( - 1 ) ;
2003-10-08 15:54:57 +04:00
ret = ( fflush ( ( FILE * ) context ) = = EOF ) ? - 1 : 0 ;
if ( ret < 0 )
xmlIOErr ( 0 , " fflush() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2005-11-09 11:56:26 +03:00
# ifdef LIBXML_OUTPUT_ENABLED
/**
* xmlBufferWrite :
* @ context : the xmlBuffer
* @ buffer : the data to write
* @ len : number of bytes to write
*
* Write @ len bytes from @ buffer to the xml buffer
*
* Returns the number of bytes written
*/
static int
xmlBufferWrite ( void * context , const char * buffer , int len ) {
int ret ;
ret = xmlBufferAdd ( ( xmlBufferPtr ) context , ( const xmlChar * ) buffer , len ) ;
if ( ret ! = 0 )
return ( - 1 ) ;
return ( len ) ;
}
# endif
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* 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 20:00:36 +03:00
static int
2001-03-26 20:28:29 +04:00
xmlGzfileMatch ( const char * filename ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
}
/**
2003-01-10 19:09:51 +03:00
* xmlGzfileOpen_real :
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
static void *
2003-01-10 19:09:51 +03:00
xmlGzfileOpen_real ( const char * filename ) {
2001-02-23 20:55:21 +03:00
const char * path = NULL ;
gzFile fd ;
if ( ! strcmp ( filename , " - " ) ) {
2014-06-21 00:11:40 +04:00
int duped_fd = dup ( fileno ( stdin ) ) ;
fd = gzdopen ( duped_fd , " rb " ) ;
2014-08-25 02:10:13 +04:00
if ( fd = = Z_NULL & & duped_fd > = 0 ) {
2014-06-21 00:11:40 +04:00
close ( duped_fd ) ; /* gzdOpen() does not close on failure */
}
2001-02-23 20:55:21 +03:00
return ( ( void * ) fd ) ;
}
2002-09-10 15:13:43 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2002-09-10 15:13:43 +04:00
path = & filename [ 17 ] ;
# else
2001-02-23 20:55:21 +03:00
path = & filename [ 16 ] ;
2002-09-10 15:13:43 +04:00
# endif
2002-05-01 22:32:28 +04:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2001-08-14 16:18:09 +04:00
path = & filename [ 8 ] ;
# else
2001-02-23 20:55:21 +03:00
path = & filename [ 7 ] ;
2001-08-14 16:18:09 +04:00
# endif
2009-08-11 19:51:22 +04:00
} else
2001-02-23 20:55:21 +03:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
if ( ! xmlCheckFilename ( path ) )
return ( NULL ) ;
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2017-10-09 16:35:32 +03:00
fd = xmlWrapGzOpenUtf8 ( path , " rb " ) ;
2009-08-11 19:51:22 +04:00
# else
2001-02-23 20:55:21 +03:00
fd = gzopen ( path , " rb " ) ;
2009-08-11 19:51:22 +04:00
# endif
2001-02-23 20:55:21 +03:00
return ( ( void * ) fd ) ;
}
2003-01-10 19:09:51 +03:00
/**
* xmlGzfileOpen :
* @ filename : the URI for matching
*
2022-05-06 11:58:58 +03:00
* Wrapper around xmlGzfileOpen_real if the open fails , it will
2003-06-09 14:30:33 +04:00
* try to unescape @ filename
2003-01-10 19:09:51 +03:00
*/
static void *
xmlGzfileOpen ( const char * filename ) {
char * unescaped ;
void * retval ;
2003-06-09 14:30:33 +04: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 19:09:51 +03:00
}
return retval ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
static void *
2001-02-23 20:55:21 +03:00
xmlGzfileOpenW ( const char * filename , int compression ) {
const char * path = NULL ;
char mode [ 15 ] ;
gzFile fd ;
2002-06-14 21:07:10 +04:00
snprintf ( mode , sizeof ( mode ) , " wb%d " , compression ) ;
2001-02-23 20:55:21 +03:00
if ( ! strcmp ( filename , " - " ) ) {
2014-06-21 00:11:40 +04:00
int duped_fd = dup ( fileno ( stdout ) ) ;
fd = gzdopen ( duped_fd , " rb " ) ;
2014-08-25 02:10:13 +04:00
if ( fd = = Z_NULL & & duped_fd > = 0 ) {
2014-06-21 00:11:40 +04:00
close ( duped_fd ) ; /* gzdOpen() does not close on failure */
}
2001-02-23 20:55:21 +03:00
return ( ( void * ) fd ) ;
}
2002-09-10 15:13:43 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) )
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2002-09-10 15:13:43 +04:00
path = & filename [ 17 ] ;
# else
2001-02-23 20:55:21 +03:00
path = & filename [ 16 ] ;
2002-09-10 15:13:43 +04:00
# endif
2002-05-01 22:32:28 +04:00
else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2001-08-14 16:18:09 +04:00
path = & filename [ 8 ] ;
# else
2001-05-31 22:43:43 +04:00
path = & filename [ 7 ] ;
2001-08-14 16:18:09 +04:00
# endif
2009-08-11 19:51:22 +04:00
} else
2001-02-23 20:55:21 +03:00
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
2022-03-01 01:22:50 +03:00
# if defined(_WIN32)
2017-10-09 16:35:32 +03:00
fd = xmlWrapGzOpenUtf8 ( path , mode ) ;
2009-08-11 19:51:22 +04:00
# else
2001-02-23 20:55:21 +03:00
fd = gzopen ( path , mode ) ;
2009-08-11 19:51:22 +04:00
# endif
2001-02-23 20:55:21 +03:00
return ( ( void * ) fd ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03: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 .
*
2017-06-18 00:20:38 +03:00
* Returns the number of bytes read .
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlGzfileRead ( void * context , char * buffer , int len ) {
2003-10-08 15:54:57 +04:00
int ret ;
ret = gzread ( ( gzFile ) context , & buffer [ 0 ] , len ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " gzread() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlGzfileWrite ( void * context , const char * buffer , int len ) {
2003-10-08 15:54:57 +04:00
int ret ;
ret = gzwrite ( ( gzFile ) context , ( char * ) & buffer [ 0 ] , len ) ;
if ( ret < 0 ) xmlIOErr ( 0 , " gzwrite() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlGzfileClose :
* @ context : the I / O context
*
* Close a compressed I / O channel
*/
2001-07-23 23:10:52 +04:00
static int
2001-02-23 20:55:21 +03:00
xmlGzfileClose ( void * context ) {
2003-10-08 15:54:57 +04:00
int ret ;
ret = ( gzclose ( ( gzFile ) context ) = = Z_OK ) ? 0 : - 1 ;
if ( ret < 0 ) xmlIOErr ( 0 , " gzclose() " ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2017-11-13 19:08:38 +03:00
# endif /* LIBXML_ZLIB_ENABLED */
2001-02-23 20:55:21 +03:00
2015-11-03 10:46:29 +03:00
# ifdef LIBXML_LZMA_ENABLED
2011-09-18 18:59:13 +04:00
/************************************************************************
* *
* I / O for compressed file accesses *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-08-26 02:22:33 +03:00
# include "private/xzlib.h"
2011-09-18 18:59:13 +04:00
/**
* xmlXzfileMatch :
* @ filename : the URI for matching
*
* input from compressed file test
*
* Returns 1 if matches , 0 otherwise
*/
static int
xmlXzfileMatch ( const char * filename ATTRIBUTE_UNUSED ) {
return ( 1 ) ;
}
/**
* xmlXzFileOpen_real :
* @ filename : the URI for matching
*
* input from compressed file open
* if @ filename is " " then the standard input is used
*
* Returns an I / O context or NULL in case of error
*/
static void *
xmlXzfileOpen_real ( const char * filename ) {
const char * path = NULL ;
xzFile fd ;
if ( ! strcmp ( filename , " - " ) ) {
2013-12-12 11:02:40 +04:00
fd = __libxml2_xzdopen ( dup ( fileno ( stdin ) ) , " rb " ) ;
2011-09-18 18:59:13 +04:00
return ( ( void * ) fd ) ;
}
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file://localhost/ " , 17 ) ) {
path = & filename [ 16 ] ;
} else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/// " , 8 ) ) {
path = & filename [ 7 ] ;
} else if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " file:/ " , 6 ) ) {
/* lots of generators seems to lazy to read RFC 1738 */
path = & filename [ 5 ] ;
} else
path = filename ;
if ( path = = NULL )
return ( NULL ) ;
if ( ! xmlCheckFilename ( path ) )
return ( NULL ) ;
2012-01-26 12:56:22 +04:00
fd = __libxml2_xzopen ( path , " rb " ) ;
2011-09-18 18:59:13 +04:00
return ( ( void * ) fd ) ;
}
/**
* xmlXzfileOpen :
* @ filename : the URI for matching
*
* Wrapper around xmlXzfileOpen_real that try it with an unescaped
* version of @ filename , if this fails fallback to @ filename
*
* Returns a handler or NULL in case or failure
*/
static void *
xmlXzfileOpen ( const char * filename ) {
char * unescaped ;
void * retval ;
retval = xmlXzfileOpen_real ( filename ) ;
if ( retval = = NULL ) {
unescaped = xmlURIUnescapeString ( filename , 0 , NULL ) ;
if ( unescaped ! = NULL ) {
retval = xmlXzfileOpen_real ( unescaped ) ;
}
xmlFree ( unescaped ) ;
}
return retval ;
}
/**
* xmlXzfileRead :
* @ context : the I / O context
* @ buffer : where to drop data
* @ len : number of bytes to write
*
* Read @ len bytes to @ buffer from the compressed I / O channel .
*
* Returns the number of bytes written
*/
static int
xmlXzfileRead ( void * context , char * buffer , int len ) {
int ret ;
2012-01-26 12:56:22 +04:00
ret = __libxml2_xzread ( ( xzFile ) context , & buffer [ 0 ] , len ) ;
2011-09-18 18:59:13 +04:00
if ( ret < 0 ) xmlIOErr ( 0 , " xzread() " ) ;
return ( ret ) ;
}
/**
* xmlXzfileClose :
* @ context : the I / O context
*
* Close a compressed I / O channel
*/
static int
xmlXzfileClose ( void * context ) {
int ret ;
2012-01-26 12:56:22 +04:00
ret = ( __libxml2_xzclose ( ( xzFile ) context ) = = LZMA_OK ) ? 0 : - 1 ;
2011-09-18 18:59:13 +04:00
if ( ret < 0 ) xmlIOErr ( 0 , " xzclose() " ) ;
return ( ret ) ;
}
2015-11-03 10:46:29 +03:00
# endif /* LIBXML_LZMA_ENABLED */
2011-09-18 18:59:13 +04:00
2001-02-23 20:55:21 +03:00
# ifdef LIBXML_HTTP_ENABLED
/************************************************************************
* *
* I / O for HTTP file accesses *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-07-23 23:10:52 +04:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 23:10:52 +04:00
typedef struct xmlIOHTTPWriteCtxt_
{
int compression ;
char * uri ;
void * doc_buff ;
} xmlIOHTTPWriteCtxt , * xmlIOHTTPWriteCtxtPtr ;
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-07-23 23:10:52 +04:00
# 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
2009-08-11 19:51:22 +04:00
* * the number " 4 " is hardcoded . If zlib is ever patched to
2001-07-23 23:10:52 +04:00
* * 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 18:47:38 +04:00
# ifdef DEBUG_HTTP
2001-07-23 23:10:52 +04:00
int z_err ;
2003-07-31 18:47:38 +04:00
# endif
2001-07-23 23:10:52 +04:00
if ( buff = = NULL )
return ;
xmlFree ( buff - > zbuff ) ;
# ifdef DEBUG_HTTP
2003-07-31 18:47:38 +04:00
z_err = deflateEnd ( & buff - > zctrl ) ;
2001-07-23 23:10:52 +04:00
if ( z_err ! = Z_OK )
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeZMemBuff: Error releasing zlib context: %d \n " ,
z_err ) ;
2003-07-31 18:47:38 +04:00
# else
deflateEnd ( & buff - > zctrl ) ;
2003-08-01 19:55:39 +04:00
# endif
2001-07-23 23:10:52 +04: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
2009-08-11 19:51:22 +04:00
* would be created if gzopen / gzwrite / gzclose were being used to
2001-07-23 23:10:52 +04:00
* 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 15:54:57 +04:00
xmlIOErrMemory ( " creating buffer context " ) ;
2001-07-23 23:10:52 +04: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 15:54:57 +04:00
xmlIOErrMemory ( " creating buffer " ) ;
2001-07-23 23:10:52 +04: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 15:54:57 +04:00
xmlChar msg [ 500 ] ;
2001-07-23 23:10:52 +04:00
xmlFreeZMemBuff ( buff ) ;
buff = NULL ;
2003-10-08 15:54:57 +04:00
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlCreateZMemBuff: %s %d \n " ,
2003-10-08 15:54:57 +04:00
" Error initializing compression context. ZLIB error: " ,
z_err ) ;
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 23:10:52 +04:00
return ( NULL ) ;
}
/* Set the header data. The CRC will be needed for the trailer */
2005-07-29 03:49:35 +04:00
buff - > crc = crc32 ( 0L , NULL , 0 ) ;
2002-06-14 21:07:10 +04:00
hdr_lgth = snprintf ( ( char * ) buff - > zbuff , buff - > size ,
" %c%c%c%c%c%c%c%c%c%c " ,
2009-08-11 19:51:22 +04:00
GZ_MAGIC1 , GZ_MAGIC2 , Z_DEFLATED ,
2001-07-23 23:10:52 +04:00
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
2009-08-11 19:51:22 +04:00
if ( cur_used > new_size )
2001-07-23 23:10:52 +04:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlZMemBuffExtend: %s \n %s %d bytes. \n " ,
" Buffer overwrite detected during compressed memory " ,
2009-08-11 19:51:22 +04:00
" buffer extension. Overflowed by " ,
2001-07-23 23:10:52 +04:00
( 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 15:54:57 +04:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlZMemBuffExtend: %s %lu bytes. \n " ,
2003-10-08 15:54:57 +04:00
" Allocation failure extending output buffer to " ,
2016-08-22 12:44:18 +03:00
( unsigned long ) new_size ) ;
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 23:10:52 +04: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 15:54:57 +04:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlZMemBuffAppend: %s %d %s - %d " ,
2001-07-23 23:10:52 +04:00
" Compression error while appending " ,
len , " bytes to buffer. ZLIB error " , z_err ) ;
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 23:10:52 +04: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 15:54:57 +04:00
else {
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlZMemBuffGetContent: %s - %d \n " ,
2003-10-08 15:54:57 +04:00
" Error flushing zlib buffers. Error code " , z_err ) ;
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
}
2009-08-11 19:51:22 +04:00
2001-07-23 23:10:52 +04:00
return ( zlgth ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2017-11-13 19:08:38 +03:00
# endif /* LIBXML_ZLIB_ENABLED */
2001-07-23 23:10:52 +04:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 23:10:52 +04: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 15:15:18 +04:00
xmlFree ( ctxt - > uri ) ;
2001-07-23 23:10:52 +04:00
if ( ctxt - > doc_buff ! = NULL ) {
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-07-23 23:10:52 +04:00
if ( ctxt - > compression > 0 ) {
xmlFreeZMemBuff ( ctxt - > doc_buff ) ;
}
else
# endif
{
xmlOutputBufferClose ( ctxt - > doc_buff ) ;
}
}
2002-10-14 15:15:18 +04:00
xmlFree ( ctxt ) ;
2001-07-23 23:10:52 +04:00
return ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03:00
/**
* xmlIOHTTPMatch :
* @ filename : the URI for matching
*
* check if the URI matches an HTTP one
*
* Returns 1 if matches , 0 otherwise
*/
2002-05-01 22:32:28 +04:00
int
2001-02-23 20:55:21 +03:00
xmlIOHTTPMatch ( const char * filename ) {
2002-05-01 22:32:28 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " http:// " , 7 ) )
2001-02-23 20:55:21 +03: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 22:32:28 +04:00
void *
2001-02-23 20:55:21 +03:00
xmlIOHTTPOpen ( const char * filename ) {
return ( xmlNanoHTTPOpen ( filename , NULL ) ) ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 23:10:52 +04:00
/**
2002-12-11 17:23:49 +03:00
* xmlIOHTTPOpenW :
2001-07-23 23:10:52 +04: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 *
2017-06-17 15:12:53 +03:00
xmlIOHTTPOpenW ( const char * post_uri , int compression ATTRIBUTE_UNUSED )
2002-01-18 19:23:55 +03:00
{
2001-07-23 23:10:52 +04:00
2002-01-18 19:23:55 +03:00
xmlIOHTTPWriteCtxtPtr ctxt = NULL ;
2001-07-23 23:10:52 +04:00
2002-01-18 19:23:55 +03:00
if ( post_uri = = NULL )
return ( NULL ) ;
2001-07-23 23:10:52 +04:00
2002-01-18 19:23:55 +03:00
ctxt = xmlMalloc ( sizeof ( xmlIOHTTPWriteCtxt ) ) ;
if ( ctxt = = NULL ) {
2003-10-08 15:54:57 +04:00
xmlIOErrMemory ( " creating HTTP output context " ) ;
2002-01-18 19:23:55 +03:00
return ( NULL ) ;
2001-07-23 23:10:52 +04:00
}
2002-01-18 19:23:55 +03:00
( void ) memset ( ctxt , 0 , sizeof ( xmlIOHTTPWriteCtxt ) ) ;
2001-07-23 23:10:52 +04:00
2002-01-18 19:23:55 +03:00
ctxt - > uri = ( char * ) xmlStrdup ( ( const xmlChar * ) post_uri ) ;
if ( ctxt - > uri = = NULL ) {
2003-10-08 15:54:57 +04:00
xmlIOErrMemory ( " copying URI " ) ;
2002-01-18 19:23:55 +03:00
xmlFreeHTTPWriteCtxt ( ctxt ) ;
return ( NULL ) ;
2001-07-23 23:10:52 +04:00
}
/*
2002-01-18 19:23:55 +03: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 23:10:52 +04:00
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2002-01-18 19:23:55 +03:00
if ( ( compression > 0 ) & & ( compression < = 9 ) ) {
ctxt - > compression = compression ;
ctxt - > doc_buff = xmlCreateZMemBuff ( compression ) ;
} else
2001-07-23 23:10:52 +04:00
# endif
{
2002-01-18 19:23:55 +03:00
/* Any character conversions should have been done before this */
2001-07-23 23:10:52 +04:00
2008-09-01 17:08:57 +04:00
ctxt - > doc_buff = xmlAllocOutputBufferInternal ( NULL ) ;
2001-07-23 23:10:52 +04:00
}
2002-01-18 19:23:55 +03:00
if ( ctxt - > doc_buff = = NULL ) {
xmlFreeHTTPWriteCtxt ( ctxt ) ;
ctxt = NULL ;
2001-07-23 23:10:52 +04:00
}
2002-01-18 19:23:55 +03:00
return ( ctxt ) ;
2001-07-23 23:10:52 +04:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2008-09-01 17:08:57 +04:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 23:10:52 +04: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 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03: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
*/
2009-08-11 19:51:22 +04:00
int
2001-02-23 20:55:21 +03:00
xmlIOHTTPRead ( void * context , char * buffer , int len ) {
2004-11-08 14:54:28 +03:00
if ( ( buffer = = NULL ) | | ( len < 0 ) ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
return ( xmlNanoHTTPRead ( context , & buffer [ 0 ] , len ) ) ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 23:10:52 +04: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
2009-08-11 19:51:22 +04:00
xmlIOHTTPWrite ( void * context , const char * buffer , int len ) {
2001-07-23 23:10:52 +04:00
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 */
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2009-08-11 19:51:22 +04:00
if ( ctxt - > compression > 0 )
2001-07-23 23:10:52 +04:00
len = xmlZMemBuffAppend ( ctxt - > doc_buff , buffer , len ) ;
else
# endif
len = xmlOutputBufferWrite ( ctxt - > doc_buff , len , buffer ) ;
if ( len < 0 ) {
2003-10-08 15:54:57 +04:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlIOHTTPWrite: %s \n %s '%s'. \n " ,
2001-07-23 23:10:52 +04:00
" Error appending to internal buffer. " ,
" Error sending document to URI " ,
ctxt - > uri ) ;
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 23:10:52 +04:00
}
}
return ( len ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03:00
/**
* xmlIOHTTPClose :
* @ context : the I / O context
*
* Close an HTTP I / O channel
2002-12-11 17:23:49 +03:00
*
* Returns 0
2001-02-23 20:55:21 +03:00
*/
2002-05-01 22:32:28 +04:00
int
2001-02-23 20:55:21 +03:00
xmlIOHTTPClose ( void * context ) {
xmlNanoHTTPClose ( context ) ;
2001-07-23 23:10:52 +04:00
return 0 ;
2001-02-23 20:55:21 +03:00
}
2001-07-23 23:10:52 +04:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-07-23 23:10:52 +04: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 */
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-07-23 23:10:52 +04:00
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 ;
2012-07-16 10:22:54 +04:00
http_content = ( char * ) xmlBufContent ( dctxt - > buffer ) ;
content_lgth = xmlBufUse ( dctxt - > buffer ) ;
2001-07-23 23:10:52 +04:00
}
if ( http_content = = NULL ) {
2003-10-08 15:54:57 +04:00
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlIOHTTPCloseWrite: %s '%s' %s '%s'. \n " ,
2003-10-08 15:54:57 +04:00
" Error retrieving content. \n Unable to " ,
http_mthd , " data to URI " , ctxt - > uri ) ;
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
2001-07-23 23:10:52 +04:00
}
else {
http_ctxt = xmlNanoHTTPMethod ( ctxt - > uri , http_mthd , http_content ,
2009-08-11 19:51:22 +04:00
& content_type , content_encoding ,
2001-07-23 23:10:52 +04:00
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 ,
2009-08-11 19:51:22 +04:00
* * dump them to separate files instead of the
2001-07-23 23:10:52 +04:00
* * standard error context .
*/
dump_name = tempnam ( NULL , " lxml " ) ;
if ( dump_name ! = NULL ) {
2002-06-14 21:07:10 +04:00
( void ) snprintf ( buffer , sizeof ( buffer ) , " %s.content " , dump_name ) ;
2001-07-23 23:10:52 +04:00
2003-07-20 19:21:30 +04:00
tst_file = fopen ( buffer , " wb " ) ;
2001-07-23 23:10:52 +04:00
if ( tst_file ! = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" Transmitted content saved in file: %s \n " , buffer ) ;
2022-09-01 04:14:13 +03:00
fwrite ( http_content , 1 , content_lgth , tst_file ) ;
2001-07-23 23:10:52 +04:00
fclose ( tst_file ) ;
}
2002-06-14 21:07:10 +04:00
( void ) snprintf ( buffer , sizeof ( buffer ) , " %s.reply " , dump_name ) ;
2003-07-20 19:21:30 +04:00
tst_file = fopen ( buffer , " wb " ) ;
2001-07-23 23:10:52 +04:00
if ( tst_file ! = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" Reply content saved in file: %s \n " , buffer ) ;
while ( ( avail = xmlNanoHTTPRead ( http_ctxt ,
buffer , sizeof ( buffer ) ) ) > 0 ) {
2022-09-01 04:14:13 +03:00
fwrite ( buffer , 1 , avail , tst_file ) ;
2001-07-23 23:10:52 +04:00
}
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 15:54:57 +04:00
else {
xmlChar msg [ 500 ] ;
xmlStrPrintf ( msg , 500 ,
2016-05-13 10:13:17 +03:00
" xmlIOHTTPCloseWrite: HTTP '%s' of %d %s \n '%s' %s %d \n " ,
2001-07-23 23:10:52 +04:00
http_mthd , content_lgth ,
" bytes to URI " , ctxt - > uri ,
" failed. HTTP return code: " , http_rtn ) ;
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_WRITE , ( const char * ) msg ) ;
}
2001-07-23 23:10:52 +04: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 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03: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 22:32:28 +04:00
int
2001-02-23 20:55:21 +03:00
xmlIOFTPMatch ( const char * filename ) {
2002-05-01 22:32:28 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST filename , BAD_CAST " ftp:// " , 6 ) )
2001-02-23 20:55:21 +03: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 22:32:28 +04:00
void *
2001-02-23 20:55:21 +03: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
*/
2009-08-11 19:51:22 +04:00
int
2001-02-23 20:55:21 +03:00
xmlIOFTPRead ( void * context , char * buffer , int len ) {
2004-11-08 14:54:28 +03:00
if ( ( buffer = = NULL ) | | ( len < 0 ) ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
return ( xmlNanoFTPRead ( context , & buffer [ 0 ] , len ) ) ;
}
/**
* xmlIOFTPClose :
* @ context : the I / O context
*
* Close an FTP I / O channel
2002-12-11 17:23:49 +03:00
*
* Returns 0
2001-02-23 20:55:21 +03:00
*/
2002-05-01 22:32:28 +04:00
int
2001-02-23 20:55:21 +03:00
xmlIOFTPClose ( void * context ) {
2001-07-23 23:10:52 +04:00
return ( xmlNanoFTPClose ( context ) ) ;
2001-02-23 20:55:21 +03:00
}
# endif /* LIBXML_FTP_ENABLED */
/**
* xmlRegisterInputCallbacks :
2001-03-24 20:00:36 +03:00
* @ matchFunc : the xmlInputMatchCallback
* @ openFunc : the xmlInputOpenCallback
* @ readFunc : the xmlInputReadCallback
* @ closeFunc : the xmlInputCloseCallback
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
xmlRegisterInputCallbacks ( xmlInputMatchCallback matchFunc ,
xmlInputOpenCallback openFunc , xmlInputReadCallback readFunc ,
xmlInputCloseCallback closeFunc ) {
2001-02-23 20:55:21 +03:00
if ( xmlInputCallbackNr > = MAX_INPUT_CALLBACK ) {
return ( - 1 ) ;
}
2001-03-24 20:00:36 +03:00
xmlInputCallbackTable [ xmlInputCallbackNr ] . matchcallback = matchFunc ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . opencallback = openFunc ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . readcallback = readFunc ;
xmlInputCallbackTable [ xmlInputCallbackNr ] . closecallback = closeFunc ;
2003-09-23 11:43:19 +04:00
xmlInputCallbackInitialized = 1 ;
2001-02-23 20:55:21 +03:00
return ( xmlInputCallbackNr + + ) ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlRegisterOutputCallbacks :
2001-03-24 20:00:36 +03:00
* @ matchFunc : the xmlOutputMatchCallback
* @ openFunc : the xmlOutputOpenCallback
* @ writeFunc : the xmlOutputWriteCallback
* @ closeFunc : the xmlOutputCloseCallback
2001-02-23 20:55:21 +03: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 20:00:36 +03:00
xmlRegisterOutputCallbacks ( xmlOutputMatchCallback matchFunc ,
xmlOutputOpenCallback openFunc , xmlOutputWriteCallback writeFunc ,
xmlOutputCloseCallback closeFunc ) {
2009-08-24 15:52:23 +04:00
if ( xmlOutputCallbackNr > = MAX_OUTPUT_CALLBACK ) {
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
2001-03-24 20:00:36 +03:00
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . matchcallback = matchFunc ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . opencallback = openFunc ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . writecallback = writeFunc ;
xmlOutputCallbackTable [ xmlOutputCallbackNr ] . closecallback = closeFunc ;
2003-09-23 11:43:19 +04:00
xmlOutputCallbackInitialized = 1 ;
2001-02-23 20:55:21 +03:00
return ( xmlOutputCallbackNr + + ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlRegisterDefaultInputCallbacks :
*
* Registers the default compiled - in I / O handlers .
*/
void
2006-10-11 20:43:06 +04:00
xmlRegisterDefaultInputCallbacks ( void ) {
2001-02-23 20:55:21 +03:00
if ( xmlInputCallbackInitialized )
return ;
xmlRegisterInputCallbacks ( xmlFileMatch , xmlFileOpen ,
xmlFileRead , xmlFileClose ) ;
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-02-23 20:55:21 +03:00
xmlRegisterInputCallbacks ( xmlGzfileMatch , xmlGzfileOpen ,
xmlGzfileRead , xmlGzfileClose ) ;
2017-11-13 19:08:38 +03:00
# endif /* LIBXML_ZLIB_ENABLED */
2015-11-03 10:46:29 +03:00
# ifdef LIBXML_LZMA_ENABLED
2011-09-18 18:59:13 +04:00
xmlRegisterInputCallbacks ( xmlXzfileMatch , xmlXzfileOpen ,
xmlXzfileRead , xmlXzfileClose ) ;
2015-11-03 10:46:29 +03:00
# endif /* LIBXML_LZMA_ENABLED */
2001-02-23 20:55:21 +03:00
# 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 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlRegisterDefaultOutputCallbacks :
*
* Registers the default compiled - in I / O handlers .
*/
void
2006-10-11 20:43:06 +04:00
xmlRegisterDefaultOutputCallbacks ( void ) {
2001-02-23 20:55:21 +03:00
if ( xmlOutputCallbackInitialized )
return ;
xmlRegisterOutputCallbacks ( xmlFileMatch , xmlFileOpenW ,
xmlFileWrite , xmlFileClose ) ;
2001-07-23 23:10:52 +04:00
# ifdef LIBXML_HTTP_ENABLED
xmlRegisterOutputCallbacks ( xmlIOHTTPMatch , xmlIOHTTPDfltOpenW ,
xmlIOHTTPWrite , xmlIOHTTPClosePut ) ;
# endif
2001-02-23 20:55:21 +03: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 .
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2001-02-23 20:55:21 +03:00
xmlRegisterOutputCallbacks ( xmlGzfileMatch , xmlGzfileOpen ,
xmlGzfileWrite , xmlGzfileClose ) ;
# endif
Nor FTP PUT . . . .
# ifdef LIBXML_FTP_ENABLED
xmlRegisterOutputCallbacks ( xmlIOFTPMatch , xmlIOFTPOpen ,
xmlIOFTPWrite , xmlIOFTPClose ) ;
# endif
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
xmlOutputCallbackInitialized = 1 ;
}
2001-07-23 23:10:52 +04:00
# ifdef LIBXML_HTTP_ENABLED
/**
2002-12-11 17:23:49 +03:00
* xmlRegisterHTTPPostCallbacks :
2001-07-23 23:10:52 +04: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 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03: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 15:54:57 +04:00
xmlIOErrMemory ( " creating input buffer " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
2022-09-01 02:18:30 +03:00
memset ( ret , 0 , sizeof ( xmlParserInputBuffer ) ) ;
2012-07-16 10:22:54 +04:00
ret - > buffer = xmlBufCreateSize ( 2 * xmlDefaultBufferSize ) ;
2001-02-23 20:55:21 +03:00
if ( ret - > buffer = = NULL ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
2012-07-16 10:22:54 +04:00
xmlBufSetAllocationScheme ( ret - > buffer , XML_BUFFER_ALLOC_DOUBLEIT ) ;
2001-02-23 20:55:21 +03:00
ret - > encoder = xmlGetCharEncodingHandler ( enc ) ;
if ( ret - > encoder ! = NULL )
2012-07-16 10:22:54 +04:00
ret - > raw = xmlBufCreateSize ( 2 * xmlDefaultBufferSize ) ;
2001-02-23 20:55:21 +03:00
else
ret - > raw = NULL ;
ret - > readcallback = NULL ;
ret - > closecallback = NULL ;
ret - > context = NULL ;
2003-09-08 05:57:30 +04:00
ret - > compressed = - 1 ;
2004-02-11 16:25:26 +03:00
ret - > rawconsumed = 0 ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 15:54:57 +04:00
xmlIOErrMemory ( " creating output buffer " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
2022-09-01 02:18:30 +03:00
memset ( ret , 0 , sizeof ( xmlOutputBuffer ) ) ;
2012-07-16 10:22:54 +04:00
ret - > buffer = xmlBufCreate ( ) ;
2001-02-23 20:55:21 +03:00
if ( ret - > buffer = = NULL ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
2022-03-05 23:46:40 +03:00
xmlBufSetAllocationScheme ( ret - > buffer , XML_BUFFER_ALLOC_DOUBLEIT ) ;
2009-03-23 22:32:04 +03:00
2008-09-01 17:08:57 +04:00
ret - > encoder = encoder ;
if ( encoder ! = NULL ) {
2012-07-16 10:22:54 +04:00
ret - > conv = xmlBufCreateSize ( 4000 ) ;
2008-09-01 17:08:57 +04:00
if ( ret - > conv = = NULL ) {
2019-07-09 10:11:01 +03:00
xmlBufFree ( ret - > buffer ) ;
2008-09-01 17:08:57 +04:00
xmlFree ( ret ) ;
return ( NULL ) ;
}
/*
* This call is designed to initiate the encoder state
*/
2012-07-16 10:22:54 +04:00
xmlCharEncOutput ( ret , 1 ) ;
2008-09-01 17:08:57 +04:00
} else
ret - > conv = NULL ;
ret - > writecallback = NULL ;
ret - > closecallback = NULL ;
ret - > context = NULL ;
ret - > written = 0 ;
return ( ret ) ;
}
/**
* xmlAllocOutputBufferInternal :
* @ encoder : the encoding converter or NULL
*
* Create a buffered parser output
*
* Returns the new parser output or NULL
*/
xmlOutputBufferPtr
xmlAllocOutputBufferInternal ( xmlCharEncodingHandlerPtr encoder ) {
xmlOutputBufferPtr ret ;
ret = ( xmlOutputBufferPtr ) xmlMalloc ( sizeof ( xmlOutputBuffer ) ) ;
if ( ret = = NULL ) {
xmlIOErrMemory ( " creating output buffer " ) ;
return ( NULL ) ;
}
2022-09-01 02:18:30 +03:00
memset ( ret , 0 , sizeof ( xmlOutputBuffer ) ) ;
2012-07-16 10:22:54 +04:00
ret - > buffer = xmlBufCreate ( ) ;
2008-09-01 17:08:57 +04:00
if ( ret - > buffer = = NULL ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
2008-08-30 16:52:26 +04:00
/*
* For conversion buffers we use the special IO handling
*/
2012-07-16 10:22:54 +04:00
xmlBufSetAllocationScheme ( ret - > buffer , XML_BUFFER_ALLOC_IO ) ;
2008-08-30 16:52:26 +04:00
2001-02-23 20:55:21 +03:00
ret - > encoder = encoder ;
if ( encoder ! = NULL ) {
2012-07-16 10:22:54 +04:00
ret - > conv = xmlBufCreateSize ( 4000 ) ;
2008-08-30 16:52:26 +04:00
if ( ret - > conv = = NULL ) {
2019-05-20 14:26:08 +03:00
xmlBufFree ( ret - > buffer ) ;
2008-08-30 16:52:26 +04:00
xmlFree ( ret ) ;
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
/*
* This call is designed to initiate the encoder state
*/
2012-07-16 10:22:54 +04:00
xmlCharEncOutput ( ret , 1 ) ;
2001-02-23 20:55:21 +03:00
} else
ret - > conv = NULL ;
ret - > writecallback = NULL ;
ret - > closecallback = NULL ;
ret - > context = NULL ;
ret - > written = 0 ;
return ( ret ) ;
}
2008-09-01 17:08:57 +04:00
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlFreeParserInputBuffer :
* @ in : a buffered parser input
*
* Free up the memory used by a buffered parser input
*/
void
xmlFreeParserInputBuffer ( xmlParserInputBufferPtr in ) {
2003-09-17 23:36:25 +04:00
if ( in = = NULL ) return ;
2001-02-23 20:55:21 +03:00
if ( in - > raw ) {
2012-07-16 10:22:54 +04:00
xmlBufFree ( in - > raw ) ;
2001-02-23 20:55:21 +03:00
in - > raw = NULL ;
}
if ( in - > encoder ! = NULL ) {
xmlCharEncCloseFunc ( in - > encoder ) ;
}
if ( in - > closecallback ! = NULL ) {
in - > closecallback ( in - > context ) ;
}
if ( in - > buffer ! = NULL ) {
2012-07-16 10:22:54 +04:00
xmlBufFree ( in - > buffer ) ;
2001-02-23 20:55:21 +03:00
in - > buffer = NULL ;
}
xmlFree ( in ) ;
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 23:19:10 +04:00
xmlOutputBufferClose ( xmlOutputBufferPtr out )
{
2001-02-23 20:55:21 +03:00
int written ;
2001-07-23 23:10:52 +04:00
int err_rc = 0 ;
2001-02-23 20:55:21 +03:00
if ( out = = NULL )
2003-10-08 23:19:10 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
if ( out - > writecallback ! = NULL )
2003-10-08 23:19:10 +04:00
xmlOutputBufferFlush ( out ) ;
2001-02-23 20:55:21 +03:00
if ( out - > closecallback ! = NULL ) {
2003-10-08 23:19:10 +04:00
err_rc = out - > closecallback ( out - > context ) ;
2001-02-23 20:55:21 +03:00
}
written = out - > written ;
if ( out - > conv ) {
2012-07-16 10:22:54 +04:00
xmlBufFree ( out - > conv ) ;
2003-10-08 23:19:10 +04:00
out - > conv = NULL ;
2001-02-23 20:55:21 +03:00
}
if ( out - > encoder ! = NULL ) {
xmlCharEncCloseFunc ( out - > encoder ) ;
}
if ( out - > buffer ! = NULL ) {
2012-07-16 10:22:54 +04:00
xmlBufFree ( out - > buffer ) ;
2003-10-08 23:19:10 +04:00
out - > buffer = NULL ;
2001-02-23 20:55:21 +03:00
}
2003-10-08 23:19:10 +04:00
if ( out - > error )
err_rc = - 1 ;
2001-02-23 20:55:21 +03:00
xmlFree ( out ) ;
2003-10-08 23:19:10 +04:00
return ( ( err_rc = = 0 ) ? written : err_rc ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
2004-06-08 14:16:42 +04:00
xmlParserInputBufferPtr
2004-06-02 20:18:40 +04:00
__xmlParserInputBufferCreateFilename ( const char * URI , xmlCharEncoding enc ) {
2001-02-23 20:55:21 +03:00
xmlParserInputBufferPtr ret ;
2001-07-08 22:35:48 +04:00
int i = 0 ;
2001-02-23 20:55:21 +03:00
void * context = NULL ;
if ( xmlInputCallbackInitialized = = 0 )
xmlRegisterDefaultInputCallbacks ( ) ;
if ( URI = = NULL ) return ( NULL ) ;
/*
2001-12-31 19:16:02 +03:00
* Try to find one of the input accept method accepting that scheme
2001-02-23 20:55:21 +03:00
* Go in reverse to give precedence to user defined handlers .
2001-07-08 22:35:48 +04:00
*/
if ( context = = NULL ) {
for ( i = xmlInputCallbackNr - 1 ; i > = 0 ; i - - ) {
if ( ( xmlInputCallbackTable [ i ] . matchcallback ! = NULL ) & &
( xmlInputCallbackTable [ i ] . matchcallback ( URI ) ! = 0 ) ) {
2003-02-19 17:51:00 +03:00
context = xmlInputCallbackTable [ i ] . opencallback ( URI ) ;
2003-10-18 15:29:40 +04:00
if ( context ! = NULL ) {
2001-07-08 22:35:48 +04:00
break ;
2003-10-18 15:29:40 +04:00
}
2001-07-08 22:35:48 +04:00
}
2001-02-23 20:55:21 +03: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 ;
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2003-10-30 01:15:13 +03:00
if ( ( xmlInputCallbackTable [ i ] . opencallback = = xmlGzfileOpen ) & &
( strcmp ( URI , " - " ) ! = 0 ) ) {
2010-01-19 18:28:48 +03:00
# if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230
ret - > compressed = ! gzdirect ( context ) ;
# else
2003-09-08 05:57:30 +04:00
if ( ( ( z_stream * ) context ) - > avail_in > 4 ) {
char * cptr , buff4 [ 4 ] ;
2003-09-10 14:51:05 +04:00
cptr = ( char * ) ( ( z_stream * ) context ) - > next_in ;
2003-09-08 05:57:30 +04:00
if ( gzread ( context , buff4 , 4 ) = = 4 ) {
if ( strncmp ( buff4 , cptr , 4 ) = = 0 )
ret - > compressed = 0 ;
else
ret - > compressed = 1 ;
gzrewind ( context ) ;
}
}
2010-01-19 18:28:48 +03:00
# endif
2003-09-08 05:57:30 +04:00
}
2013-05-10 10:01:46 +04:00
# endif
2015-11-03 10:46:29 +03:00
# ifdef LIBXML_LZMA_ENABLED
2013-05-10 10:01:46 +04:00
if ( ( xmlInputCallbackTable [ i ] . opencallback = = xmlXzfileOpen ) & &
( strcmp ( URI , " - " ) ! = 0 ) ) {
ret - > compressed = __libxml2_xzcompressed ( context ) ;
}
2003-09-08 05:57:30 +04:00
# endif
2001-02-23 20:55:21 +03:00
}
2004-07-29 11:07:16 +04:00
else
xmlInputCallbackTable [ i ] . closecallback ( context ) ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
/**
2004-06-02 20:18:40 +04:00
* xmlParserInputBufferCreateFilename :
2001-02-23 20:55:21 +03:00
* @ URI : a C string containing the URI or filename
2004-06-02 20:18:40 +04:00
* @ enc : the charset encoding if known
2001-02-23 20:55:21 +03:00
*
2004-06-02 20:18:40 +04:00
* Create a buffered parser input for the progressive parsing of a file
* If filename is " -' then we use stdin as the input.
2001-02-23 20:55:21 +03:00
* Automatic support for ZLIB / Compress compressed document is provided
* by default if found at compile - time .
2004-06-02 20:18:40 +04:00
* Do an encoding check if enc = = XML_CHAR_ENCODING_NONE
2001-02-23 20:55:21 +03:00
*
2004-06-02 20:18:40 +04:00
* Returns the new parser input or NULL
2001-02-23 20:55:21 +03:00
*/
2004-06-02 20:18:40 +04:00
xmlParserInputBufferPtr
xmlParserInputBufferCreateFilename ( const char * URI , xmlCharEncoding enc ) {
if ( ( xmlParserInputBufferCreateFilenameValue ) ) {
return xmlParserInputBufferCreateFilenameValue ( URI , enc ) ;
}
return __xmlParserInputBufferCreateFilename ( URI , enc ) ;
}
# ifdef LIBXML_OUTPUT_ENABLED
2004-06-08 14:16:42 +04:00
xmlOutputBufferPtr
2004-06-02 20:18:40 +04:00
__xmlOutputBufferCreateFilename ( const char * URI ,
2001-02-23 20:55:21 +03:00
xmlCharEncodingHandlerPtr encoder ,
2004-06-02 20:18:40 +04:00
int compression ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
xmlOutputBufferPtr ret ;
2004-05-09 06:58:44 +04:00
xmlURIPtr puri ;
2001-08-15 12:47:42 +04:00
int i = 0 ;
2001-02-23 20:55:21 +03:00
void * context = NULL ;
2004-05-09 06:58:44 +04:00
char * unescaped = NULL ;
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2004-05-09 06:58:44 +04:00
int is_file_uri = 1 ;
2004-09-28 16:33:52 +04:00
# endif
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03:00
if ( xmlOutputCallbackInitialized = = 0 )
xmlRegisterDefaultOutputCallbacks ( ) ;
if ( URI = = NULL ) return ( NULL ) ;
2004-05-09 06:58:44 +04:00
puri = xmlParseURI ( URI ) ;
if ( puri ! = NULL ) {
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2004-05-11 19:57:42 +04:00
if ( ( puri - > scheme ! = NULL ) & &
( ! xmlStrEqual ( BAD_CAST puri - > scheme , BAD_CAST " file " ) ) )
2004-05-09 06:58:44 +04:00
is_file_uri = 0 ;
2004-09-28 16:33:52 +04:00
# endif
2004-05-09 06:58:44 +04:00
/*
* try to limit the damages of the URI unescaping code .
*/
2006-10-11 13:15:00 +04:00
if ( ( puri - > scheme = = NULL ) | |
( xmlStrEqual ( BAD_CAST puri - > scheme , BAD_CAST " file " ) ) )
2004-05-09 06:58:44 +04:00
unescaped = xmlURIUnescapeString ( URI , 0 , NULL ) ;
xmlFreeURI ( puri ) ;
}
2001-08-15 12:47:42 +04:00
/*
2001-12-31 19:16:02 +03:00
* Try to find one of the output accept method accepting that scheme
2001-08-15 12:47:42 +04:00
* Go in reverse to give precedence to user defined handlers .
* try with an unescaped version of the URI
*/
if ( unescaped ! = NULL ) {
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2004-05-09 06:58:44 +04:00
if ( ( compression > 0 ) & & ( compression < = 9 ) & & ( is_file_uri = = 1 ) ) {
2001-08-15 12:47:42 +04:00
context = xmlGzfileOpenW ( unescaped , compression ) ;
if ( context ! = NULL ) {
2008-09-01 17:08:57 +04:00
ret = xmlAllocOutputBufferInternal ( encoder ) ;
2001-08-15 12:47:42 +04:00
if ( ret ! = NULL ) {
ret - > context = context ;
ret - > writecallback = xmlGzfileWrite ;
ret - > closecallback = xmlGzfileClose ;
}
xmlFree ( unescaped ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
}
# endif
2001-08-15 12:47:42 +04:00
for ( i = xmlOutputCallbackNr - 1 ; i > = 0 ; i - - ) {
if ( ( xmlOutputCallbackTable [ i ] . matchcallback ! = NULL ) & &
( xmlOutputCallbackTable [ i ] . matchcallback ( unescaped ) ! = 0 ) ) {
2017-11-13 19:08:38 +03:00
# if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2001-08-15 12:47:42 +04:00
/* 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 20:55:21 +03:00
/*
2001-08-15 12:47:42 +04:00
* If this failed try with a non - escaped URI this may be a strange
* filename
2001-02-23 20:55:21 +03:00
*/
2001-08-15 12:47:42 +04:00
if ( context = = NULL ) {
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2004-05-09 06:58:44 +04:00
if ( ( compression > 0 ) & & ( compression < = 9 ) & & ( is_file_uri = = 1 ) ) {
2003-02-19 17:51:00 +03:00
context = xmlGzfileOpenW ( URI , compression ) ;
2001-08-15 12:47:42 +04:00
if ( context ! = NULL ) {
2008-09-01 17:08:57 +04:00
ret = xmlAllocOutputBufferInternal ( encoder ) ;
2001-08-15 12:47:42 +04:00
if ( ret ! = NULL ) {
ret - > context = context ;
ret - > writecallback = xmlGzfileWrite ;
ret - > closecallback = xmlGzfileClose ;
}
2021-07-14 19:03:46 +03:00
else
xmlGzfileClose ( context ) ;
2001-08-15 12:47:42 +04:00
return ( ret ) ;
}
}
2001-07-23 23:10:52 +04:00
# endif
2001-08-15 12:47:42 +04:00
for ( i = xmlOutputCallbackNr - 1 ; i > = 0 ; i - - ) {
if ( ( xmlOutputCallbackTable [ i ] . matchcallback ! = NULL ) & &
2003-02-19 17:51:00 +03:00
( xmlOutputCallbackTable [ i ] . matchcallback ( URI ) ! = 0 ) ) {
2017-11-13 19:08:38 +03:00
# if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED)
2001-08-15 12:47:42 +04:00
/* 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 20:55:21 +03:00
}
}
2001-07-23 23:10:52 +04:00
2001-02-23 20:55:21 +03:00
if ( context = = NULL ) {
return ( NULL ) ;
}
/*
* Allocate the Output buffer front - end .
*/
2008-09-01 17:08:57 +04:00
ret = xmlAllocOutputBufferInternal ( encoder ) ;
2001-02-23 20:55:21 +03:00
if ( ret ! = NULL ) {
ret - > context = context ;
ret - > writecallback = xmlOutputCallbackTable [ i ] . writecallback ;
ret - > closecallback = xmlOutputCallbackTable [ i ] . closecallback ;
}
return ( ret ) ;
}
2004-06-02 20:18:40 +04: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 ,
int compression ATTRIBUTE_UNUSED ) {
if ( ( xmlOutputBufferCreateFilenameValue ) ) {
return xmlOutputBufferCreateFilenameValue ( URI , encoder , compression ) ;
}
return __xmlOutputBufferCreateFilename ( URI , encoder , compression ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlParserInputBufferCreateFile :
2009-08-11 19:51:22 +04:00
* @ file : a FILE *
2001-02-23 20:55:21 +03:00
* @ 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 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlOutputBufferCreateFile :
2009-08-11 19:51:22 +04:00
* @ file : a FILE *
2001-02-23 20:55:21 +03:00
* @ 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 ) ;
2008-09-01 17:08:57 +04:00
ret = xmlAllocOutputBufferInternal ( encoder ) ;
2001-02-23 20:55:21 +03:00
if ( ret ! = NULL ) {
ret - > context = file ;
ret - > writecallback = xmlFileWrite ;
ret - > closecallback = xmlFileFlush ;
}
return ( ret ) ;
}
2005-11-09 11:56:26 +03:00
/**
* xmlOutputBufferCreateBuffer :
* @ buffer : a xmlBufferPtr
* @ encoder : the encoding converter or NULL
*
* Create a buffered output for the progressive saving to a xmlBuffer
*
* Returns the new parser output or NULL
*/
xmlOutputBufferPtr
xmlOutputBufferCreateBuffer ( xmlBufferPtr buffer ,
xmlCharEncodingHandlerPtr encoder ) {
xmlOutputBufferPtr ret ;
if ( buffer = = NULL ) return ( NULL ) ;
2017-11-09 19:47:47 +03:00
ret = xmlOutputBufferCreateIO ( xmlBufferWrite , NULL , ( void * ) buffer ,
encoder ) ;
2005-11-09 11:56:26 +03:00
return ( ret ) ;
}
2012-08-06 07:16:30 +04:00
/**
* xmlOutputBufferGetContent :
* @ out : an xmlOutputBufferPtr
*
* Gives a pointer to the data currently held in the output buffer
*
* Returns a pointer to the data or NULL in case of error
*/
const xmlChar *
xmlOutputBufferGetContent ( xmlOutputBufferPtr out ) {
if ( ( out = = NULL ) | | ( out - > buffer = = NULL ) )
return ( NULL ) ;
return ( xmlBufContent ( out - > buffer ) ) ;
}
/**
* xmlOutputBufferGetSize :
* @ out : an xmlOutputBufferPtr
*
* Gives the length of the data currently held in the output buffer
*
* Returns 0 in case or error or no data is held , the size otherwise
*/
size_t
xmlOutputBufferGetSize ( xmlOutputBufferPtr out ) {
if ( ( out = = NULL ) | | ( out - > buffer = = NULL ) )
return ( 0 ) ;
return ( xmlBufUse ( out - > buffer ) ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03: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 ) {
2017-10-09 14:37:42 +03:00
ret - > context = ( void * ) ( ptrdiff_t ) fd ;
2001-02-23 20:55:21 +03: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 ;
2004-07-31 20:24:01 +04:00
int errcode ;
2001-02-23 20:55:21 +03:00
2017-06-08 23:36:09 +03:00
if ( size < 0 ) return ( NULL ) ;
2001-02-23 20:55:21 +03:00
if ( mem = = NULL ) return ( NULL ) ;
ret = xmlAllocParserInputBuffer ( enc ) ;
if ( ret ! = NULL ) {
ret - > context = ( void * ) mem ;
2022-11-13 18:30:46 +03:00
ret - > readcallback = NULL ;
2001-02-23 20:55:21 +03:00
ret - > closecallback = NULL ;
2012-07-16 10:22:54 +04:00
errcode = xmlBufAdd ( ret - > buffer , ( const xmlChar * ) mem , size ) ;
2004-07-31 20:24:01 +04:00
if ( errcode ! = 0 ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
}
return ( ret ) ;
}
2003-09-18 17:35:51 +04:00
/**
* xmlParserInputBufferCreateStatic :
* @ mem : the memory input
* @ size : the length of the memory block
* @ enc : the charset encoding if known
*
2022-11-15 00:27:58 +03:00
* DEPRECATED : Use xmlParserInputBufferCreateMem .
2003-09-18 17:35:51 +04:00
*
* Returns the new parser input or NULL
*/
xmlParserInputBufferPtr
xmlParserInputBufferCreateStatic ( const char * mem , int size ,
xmlCharEncoding enc ) {
2022-11-15 00:27:58 +03:00
return ( xmlParserInputBufferCreateMem ( mem , size , enc ) ) ;
2003-09-18 17:35:51 +04:00
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlOutputBufferCreateFd :
* @ fd : a file descriptor number
* @ encoder : the encoding converter or NULL
*
2009-08-11 19:51:22 +04:00
* Create a buffered output for the progressive saving
2001-02-23 20:55:21 +03:00
* to a file descriptor
*
* Returns the new parser output or NULL
*/
xmlOutputBufferPtr
xmlOutputBufferCreateFd ( int fd , xmlCharEncodingHandlerPtr encoder ) {
xmlOutputBufferPtr ret ;
if ( fd < 0 ) return ( NULL ) ;
2008-09-01 17:08:57 +04:00
ret = xmlAllocOutputBufferInternal ( encoder ) ;
2001-02-23 20:55:21 +03:00
if ( ret ! = NULL ) {
2017-10-09 14:37:42 +03:00
ret - > context = ( void * ) ( ptrdiff_t ) fd ;
2001-02-23 20:55:21 +03:00
ret - > writecallback = xmlFdWrite ;
2002-02-07 19:39:11 +03:00
ret - > closecallback = NULL ;
2001-02-23 20:55:21 +03:00
}
return ( ret ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03: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 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlOutputBufferCreateIO :
* @ iowrite : an I / O write function
* @ ioclose : an I / O close function
* @ ioctx : an I / O handler
2002-01-22 21:15:52 +03:00
* @ encoder : the charset encoding if known
2001-02-23 20:55:21 +03: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 ) ;
2008-09-01 17:08:57 +04:00
ret = xmlAllocOutputBufferInternal ( encoder ) ;
2001-02-23 20:55:21 +03:00
if ( ret ! = NULL ) {
ret - > context = ( void * ) ioctx ;
ret - > writecallback = iowrite ;
ret - > closecallback = ioclose ;
}
return ( ret ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
2004-06-08 14:16:42 +04:00
/**
* xmlParserInputBufferCreateFilenameDefault :
* @ func : function pointer to the new ParserInputBufferCreateFilenameFunc
*
* Registers a callback for URI input file handling
*
* Returns the old value of the registration function
*/
xmlParserInputBufferCreateFilenameFunc
xmlParserInputBufferCreateFilenameDefault ( xmlParserInputBufferCreateFilenameFunc func )
{
xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue ;
if ( old = = NULL ) {
old = __xmlParserInputBufferCreateFilename ;
}
xmlParserInputBufferCreateFilenameValue = func ;
return ( old ) ;
}
/**
* xmlOutputBufferCreateFilenameDefault :
* @ func : function pointer to the new OutputBufferCreateFilenameFunc
*
* Registers a callback for URI output file handling
*
* Returns the old value of the registration function
*/
xmlOutputBufferCreateFilenameFunc
xmlOutputBufferCreateFilenameDefault ( xmlOutputBufferCreateFilenameFunc func )
{
xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue ;
# ifdef LIBXML_OUTPUT_ENABLED
if ( old = = NULL ) {
old = __xmlOutputBufferCreateFilename ;
}
# endif
xmlOutputBufferCreateFilenameValue = func ;
return ( old ) ;
}
2001-02-23 20:55:21 +03: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 ;
2004-07-31 20:24:01 +04:00
int ret ;
2001-02-23 20:55:21 +03:00
if ( len < 0 ) return ( 0 ) ;
2003-10-08 22:58:28 +04:00
if ( ( in = = NULL ) | | ( in - > error ) ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
if ( in - > encoder ! = NULL ) {
2022-11-13 22:19:13 +03:00
size_t use , consumed ;
2004-02-11 16:25:26 +03:00
2001-02-23 20:55:21 +03:00
/*
* Store the data in the incoming raw buffer
*/
if ( in - > raw = = NULL ) {
2012-07-16 10:22:54 +04:00
in - > raw = xmlBufCreate ( ) ;
2001-02-23 20:55:21 +03:00
}
2012-07-16 10:22:54 +04:00
ret = xmlBufAdd ( in - > raw , ( const xmlChar * ) buf , len ) ;
2004-07-31 20:24:01 +04:00
if ( ret ! = 0 )
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
/*
* convert as much as possible to the parser reading buffer .
*/
2012-07-16 10:22:54 +04:00
use = xmlBufUse ( in - > raw ) ;
2018-03-17 02:03:24 +03:00
nbchars = xmlCharEncInput ( in , 1 ) ;
2001-02-23 20:55:21 +03:00
if ( nbchars < 0 ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 22:58:28 +04:00
in - > error = XML_IO_ENCODER ;
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
2022-11-13 22:19:13 +03:00
consumed = use - xmlBufUse ( in - > raw ) ;
if ( ( consumed > ULONG_MAX ) | |
( in - > rawconsumed > ULONG_MAX - ( unsigned long ) consumed ) )
in - > rawconsumed = ULONG_MAX ;
else
in - > rawconsumed + = consumed ;
2001-02-23 20:55:21 +03:00
} else {
nbchars = len ;
2012-07-16 10:22:54 +04:00
ret = xmlBufAdd ( in - > buffer , ( xmlChar * ) buf , nbchars ) ;
2004-07-31 20:24:01 +04:00
if ( ret ! = 0 )
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
# ifdef DEBUG_INPUT
xmlGenericError ( xmlGenericErrorContext ,
" I/O: pushed %d chars, buffer %d/%d \n " ,
2012-08-04 06:09:56 +04:00
nbchars , xmlBufUse ( in - > buffer ) , xmlBufLength ( in - > buffer ) ) ;
2001-02-23 20:55:21 +03:00
# endif
return ( nbchars ) ;
}
2002-03-05 23:28:20 +03: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 20:55:21 +03: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 19:16:02 +03:00
* TODO : one should be able to remove one extra copy by copying directly
2001-02-23 20:55:21 +03: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 ) {
2022-11-13 19:55:28 +03:00
xmlBufPtr buf ;
2001-02-23 20:55:21 +03:00
int res = 0 ;
2003-10-08 22:58:28 +04:00
if ( ( in = = NULL ) | | ( in - > error ) ) return ( - 1 ) ;
2003-08-19 19:01:28 +04:00
if ( ( len < = MINLEN ) & & ( len ! = 4 ) )
2001-02-23 20:55:21 +03:00
len = MINLEN ;
2003-08-19 19:01:28 +04:00
2022-11-13 19:55:28 +03:00
if ( in - > encoder = = NULL ) {
if ( in - > readcallback = = NULL )
return ( 0 ) ;
buf = in - > buffer ;
} else {
if ( in - > raw = = NULL ) {
in - > raw = xmlBufCreate ( ) ;
}
buf = in - > raw ;
2001-02-23 20:55:21 +03:00
}
/*
* Call the read method for this I / O type .
*/
if ( in - > readcallback ! = NULL ) {
2022-11-13 19:55:28 +03:00
if ( xmlBufGrow ( buf , len + 1 ) < 0 ) {
xmlIOErrMemory ( " growing input buffer " ) ;
in - > error = XML_ERR_NO_MEMORY ;
return ( - 1 ) ;
}
res = in - > readcallback ( in - > context , ( char * ) xmlBufEnd ( buf ) , len ) ;
2002-03-05 23:28:20 +03:00
if ( res < = 0 )
in - > readcallback = endOfInput ;
2022-11-13 19:55:28 +03:00
if ( res < 0 )
return ( - 1 ) ;
xmlBufAddLen ( buf , res ) ;
2001-02-23 20:55:21 +03:00
}
2013-05-10 10:01:46 +04:00
/*
* try to establish compressed status of input if not done already
*/
if ( in - > compressed = = - 1 ) {
2015-11-03 10:46:29 +03:00
# ifdef LIBXML_LZMA_ENABLED
2013-05-10 10:01:46 +04:00
if ( in - > readcallback = = xmlXzfileRead )
in - > compressed = __libxml2_xzcompressed ( in - > context ) ;
# endif
}
2001-02-23 20:55:21 +03:00
if ( in - > encoder ! = NULL ) {
2022-11-13 22:19:13 +03:00
size_t use , consumed ;
2004-02-11 16:25:26 +03:00
2001-02-23 20:55:21 +03:00
/*
* convert as much as possible to the parser reading buffer .
*/
2022-11-13 19:55:28 +03:00
use = xmlBufUse ( buf ) ;
res = xmlCharEncInput ( in , 1 ) ;
if ( res < 0 ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 22:58:28 +04:00
in - > error = XML_IO_ENCODER ;
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
2022-11-13 22:19:13 +03:00
consumed = use - xmlBufUse ( buf ) ;
if ( ( consumed > ULONG_MAX ) | |
( in - > rawconsumed > ULONG_MAX - ( unsigned long ) consumed ) )
in - > rawconsumed = ULONG_MAX ;
else
in - > rawconsumed + = consumed ;
2001-02-23 20:55:21 +03:00
}
# ifdef DEBUG_INPUT
xmlGenericError ( xmlGenericErrorContext ,
2012-07-16 10:22:54 +04:00
" I/O: read %d chars, buffer %d \n " ,
nbchars , xmlBufUse ( in - > buffer ) ) ;
2001-02-23 20:55:21 +03:00
# endif
2022-11-13 19:55:28 +03:00
return ( res ) ;
2001-02-23 20:55:21 +03:00
}
/**
* 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 ) {
2022-11-13 18:30:46 +03:00
return ( xmlParserInputBufferGrow ( in , len ) ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03: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 */
2019-09-30 18:04:54 +03:00
int chunk ; /* number of byte current processed from buf */
2001-02-23 20:55:21 +03:00
2003-10-08 22:58:28 +04:00
if ( ( out = = NULL ) | | ( out - > error ) ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
if ( len < 0 ) return ( 0 ) ;
2003-10-08 22:58:28 +04:00
if ( out - > error ) return ( - 1 ) ;
2001-02-23 20:55:21 +03: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 ) {
2012-07-16 10:22:54 +04:00
out - > conv = xmlBufCreate ( ) ;
2001-02-23 20:55:21 +03:00
}
2012-07-16 10:22:54 +04:00
ret = xmlBufAdd ( out - > buffer , ( const xmlChar * ) buf , chunk ) ;
2004-07-31 20:24:01 +04:00
if ( ret ! = 0 )
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
2012-07-16 10:22:54 +04:00
if ( ( xmlBufUse ( out - > buffer ) < MINLEN ) & & ( chunk = = len ) )
2001-02-23 20:55:21 +03:00
goto done ;
/*
* convert as much as possible to the parser reading buffer .
*/
2012-07-16 10:22:54 +04:00
ret = xmlCharEncOutput ( out , 0 ) ;
2003-02-10 18:43:53 +03:00
if ( ( ret < 0 ) & & ( ret ! = - 3 ) ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
2003-10-08 22:58:28 +04:00
out - > error = XML_IO_ENCODER ;
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
2021-07-27 17:12:54 +03:00
if ( out - > writecallback )
nbchars = xmlBufUse ( out - > conv ) ;
else
nbchars = ret > = 0 ? ret : 0 ;
2001-02-23 20:55:21 +03:00
} else {
2012-07-16 10:22:54 +04:00
ret = xmlBufAdd ( out - > buffer , ( const xmlChar * ) buf , chunk ) ;
2004-07-31 20:24:01 +04:00
if ( ret ! = 0 )
return ( - 1 ) ;
2021-07-27 17:12:54 +03:00
if ( out - > writecallback )
nbchars = xmlBufUse ( out - > buffer ) ;
else
nbchars = chunk ;
2001-02-23 20:55:21 +03:00
}
buf + = chunk ;
len - = chunk ;
if ( out - > writecallback ) {
2019-05-15 13:47:28 +03:00
if ( ( nbchars < MINLEN ) & & ( len < = 0 ) )
goto done ;
2001-02-23 20:55:21 +03:00
/*
* second write the stuff to the I / O channel
*/
if ( out - > encoder ! = NULL ) {
2009-08-11 19:51:22 +04:00
ret = out - > writecallback ( out - > context ,
2012-07-16 10:22:54 +04:00
( const char * ) xmlBufContent ( out - > conv ) , nbchars ) ;
2001-02-23 20:55:21 +03:00
if ( ret > = 0 )
2012-07-16 10:22:54 +04:00
xmlBufShrink ( out - > conv , ret ) ;
2001-02-23 20:55:21 +03:00
} else {
2009-08-11 19:51:22 +04:00
ret = out - > writecallback ( out - > context ,
2012-07-16 10:22:54 +04:00
( const char * ) xmlBufContent ( out - > buffer ) , nbchars ) ;
2001-02-23 20:55:21 +03:00
if ( ret > = 0 )
2012-07-16 10:22:54 +04:00
xmlBufShrink ( out - > buffer , ret ) ;
2001-02-23 20:55:21 +03:00
}
if ( ret < 0 ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_WRITE , NULL ) ;
2004-05-13 18:31:25 +04:00
out - > error = XML_IO_WRITE ;
return ( ret ) ;
}
2019-10-14 17:56:59 +03:00
if ( out - > written > INT_MAX - ret )
out - > written = INT_MAX ;
else
out - > written + = ret ;
2004-05-13 18:31:25 +04:00
}
written + = nbchars ;
} while ( len > 0 ) ;
done :
# ifdef DEBUG_INPUT
xmlGenericError ( xmlGenericErrorContext ,
" I/O: wrote %d chars \n " , written ) ;
# endif
return ( written ) ;
}
/**
* xmlEscapeContent :
* @ out : a pointer to an array of bytes to store the result
* @ outlen : the length of @ out
* @ in : a pointer to an array of unescaped UTF - 8 bytes
* @ inlen : the length of @ in
*
* Take a block of UTF - 8 chars in and escape them .
* Returns 0 if success , or - 1 otherwise
* The value of @ inlen after return is the number of octets consumed
* if the return value is positive , else unpredictable .
* The value of @ outlen after return is the number of octets consumed .
*/
static int
xmlEscapeContent ( unsigned char * out , int * outlen ,
const xmlChar * in , int * inlen ) {
unsigned char * outstart = out ;
const unsigned char * base = in ;
unsigned char * outend = out + * outlen ;
const unsigned char * inend ;
inend = in + ( * inlen ) ;
2009-08-11 19:51:22 +04:00
2004-05-13 18:31:25 +04:00
while ( ( in < inend ) & & ( out < outend ) ) {
2012-09-11 09:26:36 +04:00
if ( * in = = ' < ' ) {
2004-05-13 18:31:25 +04:00
if ( outend - out < 4 ) break ;
* out + + = ' & ' ;
* out + + = ' l ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( * in = = ' > ' ) {
if ( outend - out < 4 ) break ;
* out + + = ' & ' ;
* out + + = ' g ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( * in = = ' & ' ) {
if ( outend - out < 5 ) break ;
* out + + = ' & ' ;
* out + + = ' a ' ;
* out + + = ' m ' ;
* out + + = ' p ' ;
* out + + = ' ; ' ;
} else if ( * in = = ' \r ' ) {
if ( outend - out < 5 ) break ;
* out + + = ' & ' ;
* out + + = ' # ' ;
* out + + = ' 1 ' ;
* out + + = ' 3 ' ;
* out + + = ' ; ' ;
} else {
2022-09-01 02:18:30 +03:00
* out + + = * in ;
2004-05-13 18:31:25 +04:00
}
+ + in ;
2009-08-11 19:51:22 +04:00
}
2004-05-13 18:31:25 +04:00
* outlen = out - outstart ;
* inlen = in - base ;
return ( 0 ) ;
}
/**
* xmlOutputBufferWriteEscape :
* @ out : a buffered parser output
* @ str : a zero terminated UTF - 8 string
2004-05-14 07:25:14 +04:00
* @ escaping : an optional escaping function ( or NULL )
2004-05-13 18:31:25 +04:00
*
* Write the content of the string in the output I / O buffer
2019-09-30 18:04:54 +03:00
* This routine escapes the characters and then handle the I18N
2004-05-13 18:31:25 +04:00
* 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
2004-05-14 07:25:14 +04:00
xmlOutputBufferWriteEscape ( xmlOutputBufferPtr out , const xmlChar * str ,
xmlCharEncodingOutputFunc escaping ) {
2004-05-13 18:31:25 +04:00
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 */
2004-08-31 16:15:36 +04:00
int oldwritten = 0 ; /* loop guard */
2004-05-13 18:31:25 +04:00
int chunk ; /* number of byte currently processed from str */
int len ; /* number of bytes in str */
int cons ; /* byte from str consumed */
2004-11-05 13:03:46 +03:00
if ( ( out = = NULL ) | | ( out - > error ) | | ( str = = NULL ) | |
2022-11-15 00:27:58 +03:00
( out - > buffer = = NULL ) )
2012-07-16 10:22:54 +04:00
return ( - 1 ) ;
2004-05-14 07:25:14 +04:00
len = strlen ( ( const char * ) str ) ;
2004-05-13 18:31:25 +04:00
if ( len < 0 ) return ( 0 ) ;
if ( out - > error ) return ( - 1 ) ;
2004-05-14 07:25:14 +04:00
if ( escaping = = NULL ) escaping = xmlEscapeContent ;
2004-05-13 18:31:25 +04:00
do {
2004-08-31 16:15:36 +04:00
oldwritten = written ;
2004-05-13 18:31:25 +04:00
/*
* how many bytes to consume and how many bytes to store .
*/
cons = len ;
2022-05-26 04:13:07 +03:00
chunk = xmlBufAvail ( out - > buffer ) ;
2004-05-13 18:31:25 +04:00
2008-02-16 13:08:14 +03:00
/*
* make sure we have enough room to save first , if this is
* not the case force a flush , but make sure we stay in the loop
*/
if ( chunk < 40 ) {
2012-07-16 10:22:54 +04:00
if ( xmlBufGrow ( out - > buffer , 100 ) < 0 )
2008-08-30 16:52:26 +04:00
return ( - 1 ) ;
oldwritten = - 1 ;
continue ;
2008-02-16 13:08:14 +03:00
}
2004-05-13 18:31:25 +04:00
/*
* first handle encoding stuff .
*/
if ( out - > encoder ! = NULL ) {
/*
* Store the data in the incoming raw buffer
*/
if ( out - > conv = = NULL ) {
2012-07-16 10:22:54 +04:00
out - > conv = xmlBufCreate ( ) ;
2004-05-13 18:31:25 +04:00
}
2012-07-16 10:22:54 +04:00
ret = escaping ( xmlBufEnd ( out - > buffer ) ,
2004-05-14 07:25:14 +04:00
& chunk , str , & cons ) ;
2004-11-26 18:45:19 +03:00
if ( ( ret < 0 ) | | ( chunk = = 0 ) ) /* chunk==0 => nothing done */
2004-05-13 18:31:25 +04:00
return ( - 1 ) ;
2012-07-16 10:22:54 +04:00
xmlBufAddLen ( out - > buffer , chunk ) ;
2004-05-13 18:31:25 +04:00
2012-07-16 10:22:54 +04:00
if ( ( xmlBufUse ( out - > buffer ) < MINLEN ) & & ( cons = = len ) )
2004-05-13 18:31:25 +04:00
goto done ;
/*
* convert as much as possible to the output buffer .
*/
2012-07-16 10:22:54 +04:00
ret = xmlCharEncOutput ( out , 0 ) ;
2004-05-13 18:31:25 +04:00
if ( ( ret < 0 ) & & ( ret ! = - 3 ) ) {
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
out - > error = XML_IO_ENCODER ;
return ( - 1 ) ;
}
2021-07-27 17:12:54 +03:00
if ( out - > writecallback )
nbchars = xmlBufUse ( out - > conv ) ;
else
nbchars = ret > = 0 ? ret : 0 ;
2004-05-13 18:31:25 +04:00
} else {
2012-07-16 10:22:54 +04:00
ret = escaping ( xmlBufEnd ( out - > buffer ) , & chunk , str , & cons ) ;
2004-11-26 18:45:19 +03:00
if ( ( ret < 0 ) | | ( chunk = = 0 ) ) /* chunk==0 => nothing done */
2004-05-13 18:31:25 +04:00
return ( - 1 ) ;
2012-07-16 10:22:54 +04:00
xmlBufAddLen ( out - > buffer , chunk ) ;
2021-07-27 17:12:54 +03:00
if ( out - > writecallback )
nbchars = xmlBufUse ( out - > buffer ) ;
else
nbchars = chunk ;
2004-05-13 18:31:25 +04:00
}
str + = cons ;
len - = cons ;
if ( out - > writecallback ) {
2019-05-15 13:47:28 +03:00
if ( ( nbchars < MINLEN ) & & ( len < = 0 ) )
goto done ;
2004-05-13 18:31:25 +04:00
/*
* second write the stuff to the I / O channel
*/
if ( out - > encoder ! = NULL ) {
2009-08-11 19:51:22 +04:00
ret = out - > writecallback ( out - > context ,
2012-07-16 10:22:54 +04:00
( const char * ) xmlBufContent ( out - > conv ) , nbchars ) ;
2004-05-13 18:31:25 +04:00
if ( ret > = 0 )
2012-07-16 10:22:54 +04:00
xmlBufShrink ( out - > conv , ret ) ;
2004-05-13 18:31:25 +04:00
} else {
2009-08-11 19:51:22 +04:00
ret = out - > writecallback ( out - > context ,
2012-07-16 10:22:54 +04:00
( const char * ) xmlBufContent ( out - > buffer ) , nbchars ) ;
2004-05-13 18:31:25 +04:00
if ( ret > = 0 )
2012-07-16 10:22:54 +04:00
xmlBufShrink ( out - > buffer , ret ) ;
2004-05-13 18:31:25 +04:00
}
if ( ret < 0 ) {
xmlIOErr ( XML_IO_WRITE , NULL ) ;
2003-10-08 22:58:28 +04:00
out - > error = XML_IO_WRITE ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2019-10-14 17:56:59 +03:00
if ( out - > written > INT_MAX - ret )
out - > written = INT_MAX ;
else
out - > written + = ret ;
2012-07-16 10:22:54 +04:00
} else if ( xmlBufAvail ( out - > buffer ) < MINLEN ) {
xmlBufGrow ( out - > buffer , MINLEN ) ;
2001-02-23 20:55:21 +03:00
}
written + = nbchars ;
2004-08-31 16:15:36 +04:00
} while ( ( len > 0 ) & & ( oldwritten ! = written ) ) ;
2001-02-23 20:55:21 +03:00
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 ;
2009-08-11 19:51:22 +04:00
2003-10-08 22:58:28 +04:00
if ( ( out = = NULL ) | | ( out - > error ) ) return ( - 1 ) ;
2001-02-23 20:55:21 +03: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 22:58:28 +04:00
if ( ( out = = NULL ) | | ( out - > error ) ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
/*
* first handle encoding stuff .
*/
if ( ( out - > conv ! = NULL ) & & ( out - > encoder ! = NULL ) ) {
/*
2013-03-27 07:00:31 +04:00
* convert as much as possible to the parser output buffer .
2001-02-23 20:55:21 +03:00
*/
2013-03-27 07:00:31 +04:00
do {
nbchars = xmlCharEncOutput ( out , 0 ) ;
if ( nbchars < 0 ) {
xmlIOErr ( XML_IO_ENCODER , NULL ) ;
out - > error = XML_IO_ENCODER ;
return ( - 1 ) ;
}
} while ( nbchars ) ;
2001-02-23 20:55:21 +03:00
}
/*
* second flush the stuff to the I / O channel
*/
if ( ( out - > conv ! = NULL ) & & ( out - > encoder ! = NULL ) & &
( out - > writecallback ! = NULL ) ) {
ret = out - > writecallback ( out - > context ,
2012-07-16 10:22:54 +04:00
( const char * ) xmlBufContent ( out - > conv ) ,
xmlBufUse ( out - > conv ) ) ;
2001-02-23 20:55:21 +03:00
if ( ret > = 0 )
2012-07-16 10:22:54 +04:00
xmlBufShrink ( out - > conv , ret ) ;
2001-02-23 20:55:21 +03:00
} else if ( out - > writecallback ! = NULL ) {
ret = out - > writecallback ( out - > context ,
2012-07-16 10:22:54 +04:00
( const char * ) xmlBufContent ( out - > buffer ) ,
xmlBufUse ( out - > buffer ) ) ;
2001-02-23 20:55:21 +03:00
if ( ret > = 0 )
2012-07-16 10:22:54 +04:00
xmlBufShrink ( out - > buffer , ret ) ;
2001-02-23 20:55:21 +03:00
}
if ( ret < 0 ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_FLUSH , NULL ) ;
2003-10-08 22:58:28 +04:00
out - > error = XML_IO_FLUSH ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2019-10-14 17:56:59 +03:00
if ( out - > written > INT_MAX - ret )
out - > written = INT_MAX ;
else
out - > written + = ret ;
2001-02-23 20:55:21 +03:00
# ifdef DEBUG_INPUT
xmlGenericError ( xmlGenericErrorContext ,
" I/O: flushed %d chars \n " , ret ) ;
# endif
return ( ret ) ;
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
2001-07-18 23:30:27 +04:00
/**
2001-02-23 20:55:21 +03: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 ;
if ( xmlInputCallbackInitialized = = 0 )
xmlRegisterDefaultInputCallbacks ( ) ;
if ( filename = = NULL ) return ( NULL ) ;
2007-08-14 13:41:21 +04:00
2022-03-01 00:42:10 +03:00
# if defined(_WIN32)
2007-08-14 13:41:21 +04:00
# define IS_XMLPGD_SEP(ch) ((ch==' / ')||(ch=='\\'))
# else
# define IS_XMLPGD_SEP(ch) (ch==' / ')
2001-02-23 20:55:21 +03:00
# endif
strncpy ( dir , filename , 1023 ) ;
dir [ 1023 ] = 0 ;
cur = & dir [ strlen ( dir ) ] ;
while ( cur > dir ) {
2007-08-14 13:41:21 +04:00
if ( IS_XMLPGD_SEP ( * cur ) ) break ;
2001-02-23 20:55:21 +03:00
cur - - ;
}
2007-08-14 13:41:21 +04:00
if ( IS_XMLPGD_SEP ( * cur ) ) {
2001-02-23 20:55:21 +03:00
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 ) ;
2007-08-14 13:41:21 +04:00
# undef IS_XMLPGD_SEP
2001-02-23 20:55:21 +03:00
}
/****************************************************************
* *
* External entities loading *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-19 17:35:37 +04: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 ) {
2022-02-22 21:57:12 +03:00
/* Avoid unused variable warning if features are disabled. */
( void ) ctxt ;
2003-10-19 17:35:37 +04:00
# 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 14:25:13 +03:00
__xmlLoaderErr ( ctxt , " failed to load HTTP resource \" %s \" \n " ,
2003-10-19 17:35:37 +04:00
( const char * ) ret - > filename ) ;
else
2003-10-27 14:25:13 +03:00
__xmlLoaderErr ( ctxt , " failed to load HTTP resource \n " , NULL ) ;
2003-10-19 17:35:37 +04: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 ) ;
}
2006-08-30 17:11:36 +04:00
static int xmlNoNetExists ( const char * URL ) {
2001-08-24 01:17:48 +04:00
const char * path ;
if ( URL = = NULL )
return ( 0 ) ;
2002-09-10 15:13:43 +04:00
if ( ! xmlStrncasecmp ( BAD_CAST URL , BAD_CAST " file://localhost/ " , 17 ) )
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2002-09-10 15:13:43 +04:00
path = & URL [ 17 ] ;
# else
2001-08-24 01:17:48 +04:00
path = & URL [ 16 ] ;
2002-09-10 15:13:43 +04:00
# endif
2002-05-01 22:32:28 +04:00
else if ( ! xmlStrncasecmp ( BAD_CAST URL , BAD_CAST " file:/// " , 8 ) ) {
2022-03-01 01:22:50 +03:00
# if defined (_WIN32)
2001-08-24 01:17:48 +04:00
path = & URL [ 8 ] ;
# else
path = & URL [ 7 ] ;
# endif
2009-08-11 19:51:22 +04:00
} else
2001-08-24 01:17:48 +04:00
path = URL ;
2009-08-11 19:51:22 +04:00
2006-08-30 17:11:36 +04:00
return xmlCheckFilename ( path ) ;
2001-08-24 01:17:48 +04:00
}
2006-09-21 12:36:38 +04:00
# ifdef LIBXML_CATALOG_ENABLED
/**
* xmlResolveResourceFromCatalog :
* @ 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
*
* Resolves the URL and ID against the appropriate catalog .
* This function is used by xmlDefaultExternalEntityLoader and
* xmlNoNetExternalEntityLoader .
*
* Returns a new allocated URL , or NULL .
*/
2007-05-22 20:00:06 +04:00
static xmlChar *
2006-09-21 12:36:38 +04:00
xmlResolveResourceFromCatalog ( const char * URL , const char * ID ,
xmlParserCtxtPtr ctxt ) {
xmlChar * resource = NULL ;
xmlCatalogAllow pref ;
/*
* If the resource doesn ' t exists as a file ,
* try to load it from the resource pointed in the catalogs
*/
pref = xmlCatalogGetDefaults ( ) ;
if ( ( pref ! = XML_CATA_ALLOW_NONE ) & & ( ! xmlNoNetExists ( URL ) ) ) {
/*
* Do a local lookup
*/
if ( ( ctxt ! = NULL ) & & ( ctxt - > catalogs ! = NULL ) & &
( ( pref = = XML_CATA_ALLOW_ALL ) | |
( pref = = XML_CATA_ALLOW_DOCUMENT ) ) ) {
resource = xmlCatalogLocalResolve ( ctxt - > catalogs ,
( const xmlChar * ) ID ,
( const xmlChar * ) URL ) ;
}
/*
* Try a global lookup
*/
if ( ( resource = = NULL ) & &
( ( pref = = XML_CATA_ALLOW_ALL ) | |
( pref = = XML_CATA_ALLOW_GLOBAL ) ) ) {
resource = xmlCatalogResolve ( ( const xmlChar * ) ID ,
( const xmlChar * ) URL ) ;
}
if ( ( resource = = NULL ) & & ( URL ! = NULL ) )
resource = xmlStrdup ( ( const xmlChar * ) URL ) ;
/*
* TODO : do an URI lookup on the reference
*/
if ( ( resource ! = NULL ) & & ( ! xmlNoNetExists ( ( const char * ) resource ) ) ) {
xmlChar * tmp = NULL ;
if ( ( ctxt ! = NULL ) & & ( ctxt - > catalogs ! = NULL ) & &
( ( pref = = XML_CATA_ALLOW_ALL ) | |
( pref = = XML_CATA_ALLOW_DOCUMENT ) ) ) {
tmp = xmlCatalogLocalResolveURI ( ctxt - > catalogs , resource ) ;
}
if ( ( tmp = = NULL ) & &
( ( pref = = XML_CATA_ALLOW_ALL ) | |
( pref = = XML_CATA_ALLOW_GLOBAL ) ) ) {
tmp = xmlCatalogResolveURI ( resource ) ;
}
if ( tmp ! = NULL ) {
xmlFree ( resource ) ;
resource = tmp ;
}
}
}
return resource ;
}
# endif
2001-07-18 23:30:27 +04:00
/**
2001-02-23 20:55:21 +03: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
*
2019-09-30 18:04:54 +03:00
* By default we don ' t load external entities , yet .
2001-02-23 20:55:21 +03:00
*
* Returns a new allocated xmlParserInputPtr , or NULL .
*/
2003-10-19 17:35:37 +04:00
static xmlParserInputPtr
2001-02-23 20:55:21 +03:00
xmlDefaultExternalEntityLoader ( const char * URL , const char * ID ,
2003-10-19 17:35:37 +04:00
xmlParserCtxtPtr ctxt )
{
2001-02-23 20:55:21 +03:00
xmlParserInputPtr ret = NULL ;
2001-08-22 04:06:49 +04:00
xmlChar * resource = NULL ;
2003-10-19 17:35:37 +04:00
2001-02-23 20:55:21 +03:00
# ifdef DEBUG_EXTERNAL_ENTITIES
xmlGenericError ( xmlGenericErrorContext ,
2003-10-19 17:35:37 +04:00
" xmlDefaultExternalEntityLoader(%s, xxx) \n " , URL ) ;
2001-02-23 20:55:21 +03:00
# endif
2017-06-06 16:53:42 +03:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > options & XML_PARSE_NONET ) ) {
2003-11-03 17:28:31 +03:00
int options = ctxt - > options ;
2017-06-06 16:53:42 +03:00
ctxt - > options - = XML_PARSE_NONET ;
ret = xmlNoNetExternalEntityLoader ( URL , ID , ctxt ) ;
ctxt - > options = options ;
return ( ret ) ;
2003-11-03 17:28:31 +03:00
}
2006-09-21 12:36:38 +04:00
# ifdef LIBXML_CATALOG_ENABLED
resource = xmlResolveResourceFromCatalog ( URL , ID , ctxt ) ;
2001-05-10 19:34:11 +04:00
# endif
if ( resource = = NULL )
2003-10-19 17:35:37 +04:00
resource = ( xmlChar * ) URL ;
2001-05-10 19:34:11 +04:00
if ( resource = = NULL ) {
2003-10-19 17:35:37 +04:00
if ( ID = = NULL )
ID = " NULL " ;
2003-10-27 14:25:13 +03:00
__xmlLoaderErr ( ctxt , " failed to load external entity \" %s \" \n " , ID ) ;
2003-10-19 17:35:37 +04:00
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
}
2003-10-19 17:35:37 +04:00
ret = xmlNewInputFromFile ( ctxt , ( const char * ) resource ) ;
2001-08-22 20:30:37 +04:00
if ( ( resource ! = NULL ) & & ( resource ! = ( xmlChar * ) URL ) )
2003-10-19 17:35:37 +04:00
xmlFree ( resource ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
xmlDefaultExternalEntityLoader ;
2001-07-18 23:30:27 +04:00
/**
2001-02-23 20:55:21 +03: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 23:30:27 +04:00
/**
2001-02-23 20:55:21 +03: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 23:30:27 +04:00
/**
2001-02-23 20:55:21 +03:00
* xmlLoadExternalEntity :
* @ URL : the URL for the entity to load
2001-08-23 19:31:19 +04:00
* @ ID : the Public ID for the entity to load
2001-02-23 20:55:21 +03: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
*
* Returns the xmlParserInputPtr or NULL
*/
xmlParserInputPtr
xmlLoadExternalEntity ( const char * URL , const char * ID ,
xmlParserCtxtPtr ctxt ) {
2006-08-30 17:11:36 +04:00
if ( ( URL ! = NULL ) & & ( xmlNoNetExists ( URL ) = = 0 ) ) {
2003-06-09 14:30:33 +04:00
char * canonicFilename ;
xmlParserInputPtr ret ;
canonicFilename = ( char * ) xmlCanonicPath ( ( const xmlChar * ) URL ) ;
if ( canonicFilename = = NULL ) {
2003-10-08 15:54:57 +04:00
xmlIOErrMemory ( " building canonical path \n " ) ;
2003-06-09 14:30:33 +04:00
return ( NULL ) ;
}
ret = xmlCurrentExternalEntityLoader ( canonicFilename , ID , ctxt ) ;
xmlFree ( canonicFilename ) ;
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
return ( xmlCurrentExternalEntityLoader ( URL , ID , ctxt ) ) ;
}
2001-10-31 20:52:43 +03:00
/************************************************************************
2009-08-11 19:51:22 +04:00
* *
* Disabling Network access *
* *
2001-10-31 20:52:43 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* 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
2006-09-21 12:36:38 +04:00
resource = xmlResolveResourceFromCatalog ( URL , ID , ctxt ) ;
2001-10-31 20:52:43 +03:00
# endif
2006-09-21 12:36:38 +04:00
2001-10-31 20:52:43 +03:00
if ( resource = = NULL )
resource = ( xmlChar * ) URL ;
if ( resource ! = NULL ) {
2002-05-01 22:32:28 +04:00
if ( ( ! xmlStrncasecmp ( BAD_CAST resource , BAD_CAST " ftp:// " , 6 ) ) | |
( ! xmlStrncasecmp ( BAD_CAST resource , BAD_CAST " http:// " , 7 ) ) ) {
2003-10-08 15:54:57 +04:00
xmlIOErr ( XML_IO_NETWORK_ATTEMPT , ( const char * ) resource ) ;
2001-10-31 20:52:43 +03:00
if ( resource ! = ( xmlChar * ) URL )
xmlFree ( resource ) ;
return ( NULL ) ;
}
}
input = xmlDefaultExternalEntityLoader ( ( const char * ) resource , ID , ctxt ) ;
if ( resource ! = ( xmlChar * ) URL )
xmlFree ( resource ) ;
return ( input ) ;
}