2001-02-23 20:55:21 +03:00
/*
* xinclude . c : Code to implement XInclude processing
*
2003-12-09 14:35:37 +03:00
* World Wide Web Consortium W3C Last Call Working Draft 10 November 2003
* http : //www.w3.org/TR/2003/WD-xinclude-20031110
2001-02-23 20:55:21 +03:00
*
* See Copyright for the status of this software .
*
2001-06-24 16:13:24 +04:00
* daniel @ veillard . com
2001-02-23 20:55:21 +03:00
*/
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>
# include <libxml/xmlmemory.h>
# include <libxml/tree.h>
# include <libxml/parser.h>
# include <libxml/uri.h>
2013-06-17 15:01:33 +04:00
# include <libxml/xpath.h>
2001-02-23 20:55:21 +03:00
# include <libxml/xpointer.h>
# include <libxml/parserInternals.h>
# include <libxml/xmlerror.h>
2002-11-20 16:28:31 +03:00
# include <libxml/encoding.h>
2001-02-23 20:55:21 +03:00
# ifdef LIBXML_XINCLUDE_ENABLED
# include <libxml/xinclude.h>
2022-08-26 02:22:33 +03:00
# include "private/buf.h"
# include "private/error.h"
2024-06-11 20:10:41 +03:00
# include "private/parser.h"
2022-10-22 20:08:43 +03:00
# include "private/tree.h"
2022-10-30 14:21:20 +03:00
# include "private/xinclude.h"
2001-02-23 20:55:21 +03:00
2003-02-13 14:02:08 +03:00
# define XINCLUDE_MAX_DEPTH 40
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
2003-12-30 11:30:19 +03:00
* XInclude context handling *
2001-02-23 20:55:21 +03:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* An XInclude context
*/
2001-02-26 04:36:19 +03:00
typedef xmlChar * xmlURL ;
2002-09-05 14:52:10 +04:00
typedef struct _xmlXIncludeRef xmlXIncludeRef ;
typedef xmlXIncludeRef * xmlXIncludeRefPtr ;
struct _xmlXIncludeRef {
2003-12-30 11:30:19 +03:00
xmlChar * URI ; /* the fully resolved resource URL */
2002-09-05 14:52:10 +04:00
xmlChar * fragment ; /* the fragment in the URI */
2023-12-22 23:38:50 +03:00
xmlChar * base ; /* base URI of xi:include element */
2022-10-23 14:57:33 +03:00
xmlNodePtr elem ; /* the xi:include element */
2002-09-05 14:52:10 +04:00
xmlNodePtr inc ; /* the included copy */
int xml ; /* xml or txt */
2020-08-17 01:54:12 +03:00
int fallback ; /* fallback was loaded */
2022-10-22 17:09:21 +03:00
int expanding ; /* flag to detect inclusion loops */
2022-10-23 18:52:29 +03:00
int replace ; /* should the node be replaced? */
2002-09-05 14:52:10 +04:00
} ;
2022-10-23 17:02:48 +03:00
typedef struct _xmlXIncludeDoc xmlXIncludeDoc ;
typedef xmlXIncludeDoc * xmlXIncludeDocPtr ;
struct _xmlXIncludeDoc {
xmlDocPtr doc ; /* the parsed document */
xmlChar * url ; /* the URL */
int expanding ; /* flag to detect inclusion loops */
} ;
typedef struct _xmlXIncludeTxt xmlXIncludeTxt ;
typedef xmlXIncludeTxt * xmlXIncludeTxtPtr ;
struct _xmlXIncludeTxt {
xmlChar * text ; /* text string */
xmlChar * url ; /* the URL */
} ;
2001-02-23 20:55:21 +03:00
struct _xmlXIncludeCtxt {
xmlDocPtr doc ; /* the source document */
int incNr ; /* number of includes */
int incMax ; /* size of includes tab */
2002-09-05 14:52:10 +04:00
xmlXIncludeRefPtr * incTab ; /* array of included references */
2001-02-23 20:55:21 +03:00
int txtNr ; /* number of unparsed documents */
int txtMax ; /* size of unparsed documents tab */
2022-10-23 17:02:48 +03:00
xmlXIncludeTxt * txtTab ; /* array of unparsed documents */
2003-02-11 21:03:05 +03:00
2022-10-23 17:02:48 +03:00
int urlNr ; /* number of documents stacked */
int urlMax ; /* size of document stack */
xmlXIncludeDoc * urlTab ; /* document stack */
2003-02-13 14:02:08 +03:00
2003-02-11 21:03:05 +03:00
int nbErrors ; /* the number of errors detected */
2023-02-03 16:37:49 +03:00
int fatalErr ; /* abort processing */
2023-12-10 20:15:59 +03:00
int errNo ; /* error code */
2003-12-08 20:41:29 +03:00
int legacy ; /* using XINCLUDE_OLD_NS */
2003-12-09 14:35:37 +03:00
int parseFlags ; /* the flags used for parsing XML documents */
2006-09-29 13:16:00 +04:00
void * _private ; /* application data */
2020-06-05 14:43:45 +03:00
2023-02-03 16:55:53 +03:00
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
2020-06-05 14:43:45 +03:00
unsigned long incTotal ; /* total number of processed inclusions */
2023-02-03 16:55:53 +03:00
# endif
2022-10-22 17:50:18 +03:00
int depth ; /* recursion depth */
2022-10-30 14:21:20 +03:00
int isStream ; /* streaming mode */
2023-12-10 20:15:59 +03:00
xmlXPathContextPtr xpctxt ;
2023-12-18 21:43:55 +03:00
xmlStructuredErrorFunc errorHandler ;
void * errorCtxt ;
2024-06-11 15:40:28 +03:00
xmlResourceLoader resourceLoader ;
void * resourceCtxt ;
2001-02-23 20:55:21 +03:00
} ;
2022-10-22 03:19:22 +03:00
static xmlXIncludeRefPtr
xmlXIncludeExpandNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) ;
2022-10-21 17:17:48 +03:00
static int
2022-10-23 14:57:33 +03:00
xmlXIncludeLoadNode ( xmlXIncludeCtxtPtr ctxt , xmlXIncludeRefPtr ref ) ;
2022-10-21 17:17:48 +03:00
2001-05-23 17:44:21 +04:00
static int
2022-10-23 18:52:29 +03:00
xmlXIncludeDoProcess ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr tree ) ;
2001-05-23 17:44:21 +04:00
2003-08-14 19:44:40 +04:00
2003-10-09 02:38:13 +04:00
/************************************************************************
* *
2012-09-11 09:26:36 +04:00
* XInclude error handler *
2003-10-09 02:38:13 +04:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-14 19:44:40 +04:00
/**
2003-10-09 02:38:13 +04:00
* xmlXIncludeErrMemory :
2003-12-30 11:30:19 +03:00
* @ extra : extra information
2003-08-14 19:44:40 +04:00
*
2003-10-09 02:38:13 +04:00
* Handle an out of memory condition
2003-08-14 19:44:40 +04:00
*/
static void
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( xmlXIncludeCtxtPtr ctxt )
2003-08-14 19:44:40 +04:00
{
2024-03-18 14:12:15 +03:00
ctxt - > errNo = XML_ERR_NO_MEMORY ;
ctxt - > fatalErr = 1 ;
2024-04-18 12:57:46 +03:00
ctxt - > nbErrors + + ;
2024-03-18 14:12:15 +03:00
2023-12-18 21:43:55 +03:00
xmlRaiseMemoryError ( ctxt - > errorHandler , NULL , ctxt - > errorCtxt ,
XML_FROM_XINCLUDE , NULL ) ;
2003-10-09 02:38:13 +04:00
}
2003-08-14 19:44:40 +04:00
2003-10-09 02:38:13 +04:00
/**
* xmlXIncludeErr :
* @ ctxt : the XInclude context
* @ node : the context node
* @ msg : the error message
2003-12-30 11:30:19 +03:00
* @ extra : extra information
2003-10-09 02:38:13 +04:00
*
2003-12-08 20:41:29 +03:00
* Handle an XInclude error
2003-10-09 02:38:13 +04:00
*/
2016-05-13 10:13:17 +03:00
static void LIBXML_ATTR_FORMAT ( 4 , 0 )
2003-10-09 02:38:13 +04:00
xmlXIncludeErr ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node , int error ,
const char * msg , const xmlChar * extra )
{
2023-12-22 17:14:19 +03:00
xmlStructuredErrorFunc schannel = NULL ;
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
2023-12-10 20:15:59 +03:00
int res ;
if ( ctxt - > fatalErr ! = 0 )
return ;
ctxt - > nbErrors + + ;
2023-12-22 17:14:19 +03:00
schannel = ctxt - > errorHandler ;
data = ctxt - > errorCtxt ;
if ( schannel = = NULL ) {
channel = xmlGenericError ;
data = xmlGenericErrorContext ;
}
2024-06-26 02:18:55 +03:00
res = xmlRaiseError ( schannel , channel , data , ctxt , node ,
XML_FROM_XINCLUDE , error , XML_ERR_ERROR ,
NULL , 0 , ( const char * ) extra , NULL , NULL , 0 , 0 ,
msg , ( const char * ) extra ) ;
2023-12-10 20:15:59 +03:00
if ( res < 0 ) {
ctxt - > errNo = XML_ERR_NO_MEMORY ;
ctxt - > fatalErr = 1 ;
} else {
ctxt - > errNo = error ;
}
2003-08-14 19:44:40 +04:00
}
2003-12-08 20:41:29 +03:00
/**
* xmlXIncludeGetProp :
* @ ctxt : the XInclude context
* @ cur : the node
* @ name : the attribute name
*
* Get an XInclude attribute
*
* Returns the value ( to be freed ) or NULL if not found
*/
static xmlChar *
xmlXIncludeGetProp ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr cur ,
const xmlChar * name ) {
xmlChar * ret ;
2023-12-10 20:15:59 +03:00
if ( xmlNodeGetAttrValue ( cur , name , XINCLUDE_NS , & ret ) < 0 )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2003-12-08 20:41:29 +03:00
if ( ret ! = NULL )
return ( ret ) ;
2023-12-10 20:15:59 +03:00
2003-12-08 20:41:29 +03:00
if ( ctxt - > legacy ! = 0 ) {
2023-12-10 20:15:59 +03:00
if ( xmlNodeGetAttrValue ( cur , name , XINCLUDE_OLD_NS , & ret ) < 0 )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
if ( ret ! = NULL )
return ( ret ) ;
2003-12-08 20:41:29 +03:00
}
2023-12-10 20:15:59 +03:00
if ( xmlNodeGetAttrValue ( cur , name , NULL , & ret ) < 0 )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2003-12-08 20:41:29 +03:00
return ( ret ) ;
}
2002-09-05 14:52:10 +04:00
/**
* xmlXIncludeFreeRef :
* @ ref : the XInclude reference
*
* Free an XInclude reference
*/
static void
xmlXIncludeFreeRef ( xmlXIncludeRefPtr ref ) {
if ( ref = = NULL )
return ;
if ( ref - > URI ! = NULL )
xmlFree ( ref - > URI ) ;
if ( ref - > fragment ! = NULL )
xmlFree ( ref - > fragment ) ;
2023-12-22 23:38:50 +03:00
if ( ref - > base ! = NULL )
xmlFree ( ref - > base ) ;
2002-09-05 14:52:10 +04:00
xmlFree ( ref ) ;
}
2001-05-23 17:44:21 +04:00
/**
* xmlXIncludeNewContext :
* @ doc : an XML Document
*
* Creates a new XInclude context
*
* Returns the new set
*/
2003-11-03 15:31:38 +03:00
xmlXIncludeCtxtPtr
2001-05-23 17:44:21 +04:00
xmlXIncludeNewContext ( xmlDocPtr doc ) {
xmlXIncludeCtxtPtr ret ;
if ( doc = = NULL )
return ( NULL ) ;
ret = ( xmlXIncludeCtxtPtr ) xmlMalloc ( sizeof ( xmlXIncludeCtxt ) ) ;
2023-12-10 20:15:59 +03:00
if ( ret = = NULL )
2001-05-23 17:44:21 +04:00
return ( NULL ) ;
memset ( ret , 0 , sizeof ( xmlXIncludeCtxt ) ) ;
ret - > doc = doc ;
ret - > incNr = 0 ;
ret - > incMax = 0 ;
ret - > incTab = NULL ;
2003-02-11 21:03:05 +03:00
ret - > nbErrors = 0 ;
2001-05-23 17:44:21 +04:00
return ( ret ) ;
}
/**
* xmlXIncludeFreeContext :
* @ ctxt : the XInclude context
*
* Free an XInclude context
*/
2003-11-03 15:31:38 +03:00
void
2001-05-23 17:44:21 +04:00
xmlXIncludeFreeContext ( xmlXIncludeCtxtPtr ctxt ) {
int i ;
if ( ctxt = = NULL )
return ;
2022-10-23 17:02:48 +03:00
if ( ctxt - > urlTab ! = NULL ) {
for ( i = 0 ; i < ctxt - > urlNr ; i + + ) {
xmlFreeDoc ( ctxt - > urlTab [ i ] . doc ) ;
xmlFree ( ctxt - > urlTab [ i ] . url ) ;
}
2003-02-13 14:02:08 +03:00
xmlFree ( ctxt - > urlTab ) ;
2022-10-23 17:02:48 +03:00
}
2002-09-05 14:52:10 +04:00
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
if ( ctxt - > incTab [ i ] ! = NULL )
xmlXIncludeFreeRef ( ctxt - > incTab [ i ] ) ;
2001-05-23 17:44:21 +04:00
}
2020-09-28 13:28:29 +03:00
if ( ctxt - > incTab ! = NULL )
xmlFree ( ctxt - > incTab ) ;
if ( ctxt - > txtTab ! = NULL ) {
for ( i = 0 ; i < ctxt - > txtNr ; i + + ) {
2022-10-23 17:02:48 +03:00
xmlFree ( ctxt - > txtTab [ i ] . text ) ;
xmlFree ( ctxt - > txtTab [ i ] . url ) ;
2020-09-28 13:28:29 +03:00
}
xmlFree ( ctxt - > txtTab ) ;
}
2023-12-10 20:15:59 +03:00
if ( ctxt - > xpctxt ! = NULL )
xmlXPathFreeContext ( ctxt - > xpctxt ) ;
2001-05-23 17:44:21 +04:00
xmlFree ( ctxt ) ;
}
2003-08-14 19:44:40 +04:00
/**
* xmlXIncludeParseFile :
* @ ctxt : the XInclude context
* @ URL : the URL or file path
2012-09-11 09:26:36 +04:00
*
2003-12-30 11:30:19 +03:00
* parse a document for XInclude
2003-08-14 19:44:40 +04:00
*/
static xmlDocPtr
2003-12-09 14:35:37 +03:00
xmlXIncludeParseFile ( xmlXIncludeCtxtPtr ctxt , const char * URL ) {
2023-12-10 20:15:59 +03:00
xmlDocPtr ret = NULL ;
2003-08-14 19:44:40 +04:00
xmlParserCtxtPtr pctxt ;
2003-12-09 14:35:37 +03:00
xmlParserInputPtr inputStream ;
2003-08-14 19:44:40 +04:00
xmlInitParser ( ) ;
2003-12-09 14:35:37 +03:00
pctxt = xmlNewParserCtxt ( ) ;
2003-08-14 19:44:40 +04:00
if ( pctxt = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2003-12-09 14:35:37 +03:00
return ( NULL ) ;
}
2023-12-18 21:43:55 +03:00
if ( ctxt - > errorHandler ! = NULL )
xmlCtxtSetErrorHandler ( pctxt , ctxt - > errorHandler , ctxt - > errorCtxt ) ;
2024-06-11 15:40:28 +03:00
if ( ctxt - > resourceLoader ! = NULL )
xmlCtxtSetResourceLoader ( pctxt , ctxt - > resourceLoader ,
ctxt - > resourceCtxt ) ;
2006-09-29 13:16:00 +04:00
/*
* pass in the application data to the parser context .
*/
pctxt - > _private = ctxt - > _private ;
2012-09-11 09:26:36 +04:00
2003-12-09 14:35:37 +03:00
/*
2003-12-30 11:30:19 +03:00
* try to ensure that new documents included are actually
2003-12-09 14:35:37 +03:00
* built with the same dictionary as the including document .
*/
2009-08-25 21:24:15 +04:00
if ( ( ctxt - > doc ! = NULL ) & & ( ctxt - > doc - > dict ! = NULL ) ) {
if ( pctxt - > dict ! = NULL )
xmlDictFree ( pctxt - > dict ) ;
2003-12-09 14:35:37 +03:00
pctxt - > dict = ctxt - > doc - > dict ;
xmlDictReference ( pctxt - > dict ) ;
}
2024-06-17 13:54:46 +03:00
/*
* We set DTDLOAD to make sure that ID attributes declared in
* external DTDs are detected .
*/
xmlCtxtUseOptions ( pctxt , ctxt - > parseFlags | XML_PARSE_DTDLOAD ) ;
2012-09-11 09:26:36 +04:00
2024-06-11 20:10:41 +03:00
inputStream = xmlLoadResource ( pctxt , URL , NULL , XML_RESOURCE_XINCLUDE ) ;
2023-12-10 20:15:59 +03:00
if ( inputStream = = NULL )
goto error ;
2003-08-14 19:44:40 +04:00
2024-07-07 20:21:46 +03:00
if ( inputPush ( pctxt , inputStream ) < 0 ) {
xmlFreeInputStream ( inputStream ) ;
goto error ;
}
2003-12-09 14:35:37 +03:00
2003-08-14 19:44:40 +04:00
xmlParseDocument ( pctxt ) ;
2003-12-31 17:05:15 +03:00
if ( pctxt - > wellFormed ) {
2003-08-14 19:44:40 +04:00
ret = pctxt - > myDoc ;
2003-12-31 17:05:15 +03:00
}
2003-08-14 19:44:40 +04:00
else {
ret = NULL ;
2004-03-22 18:22:58 +03:00
if ( pctxt - > myDoc ! = NULL )
2004-01-23 16:15:13 +03:00
xmlFreeDoc ( pctxt - > myDoc ) ;
2003-08-14 19:44:40 +04:00
pctxt - > myDoc = NULL ;
}
2023-12-10 20:15:59 +03:00
error :
if ( pctxt - > errNo = = XML_ERR_NO_MEMORY )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2003-08-14 19:44:40 +04:00
xmlFreeParserCtxt ( pctxt ) ;
2012-09-11 09:26:36 +04:00
2003-08-14 19:44:40 +04:00
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlXIncludeAddNode :
* @ ctxt : the XInclude context
2002-09-05 14:52:10 +04:00
* @ cur : the new node
2012-09-11 09:26:36 +04:00
*
2001-02-23 20:55:21 +03:00
* Add a new node to process to an XInclude context
*/
2022-10-23 14:57:33 +03:00
static xmlXIncludeRefPtr
2002-09-05 14:52:10 +04:00
xmlXIncludeAddNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr cur ) {
2023-12-22 23:38:50 +03:00
xmlXIncludeRefPtr ref = NULL ;
xmlXIncludeRefPtr ret = NULL ;
xmlURIPtr uri = NULL ;
xmlChar * href = NULL ;
xmlChar * parse = NULL ;
2002-09-05 14:52:10 +04:00
xmlChar * fragment = NULL ;
2023-12-22 23:38:50 +03:00
xmlChar * base = NULL ;
xmlChar * tmp ;
int xml = 1 ;
2003-02-13 14:02:08 +03:00
int local = 0 ;
2023-12-10 20:15:59 +03:00
int res ;
2002-09-05 14:52:10 +04:00
if ( ctxt = = NULL )
2022-10-23 14:57:33 +03:00
return ( NULL ) ;
2002-09-05 14:52:10 +04:00
if ( cur = = NULL )
2022-10-23 14:57:33 +03:00
return ( NULL ) ;
2002-09-05 14:52:10 +04:00
2023-12-22 23:38:50 +03:00
/*
* read the attributes
*/
2003-12-09 14:35:37 +03:00
fragment = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_PARSE_XPOINTER ) ;
2002-09-05 14:52:10 +04:00
2023-12-22 23:38:50 +03:00
href = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_HREF ) ;
if ( href = = NULL ) {
if ( fragment = = NULL ) {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_NO_HREF ,
" href or xpointer must be present \n " , parse ) ;
goto error ;
}
href = xmlStrdup ( BAD_CAST " " ) ; /* @@@@ href is now optional */
if ( href = = NULL ) {
xmlXIncludeErrMemory ( ctxt ) ;
goto error ;
}
2024-07-01 17:01:24 +03:00
} else if ( xmlStrlen ( href ) > XML_MAX_URI_LENGTH ) {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_HREF_URI , " URI too long \n " ,
NULL ) ;
goto error ;
2023-12-22 23:38:50 +03:00
}
parse = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_PARSE ) ;
if ( parse ! = NULL ) {
if ( xmlStrEqual ( parse , XINCLUDE_PARSE_XML ) )
xml = 1 ;
else if ( xmlStrEqual ( parse , XINCLUDE_PARSE_TEXT ) )
xml = 0 ;
else {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_PARSE_VALUE ,
" invalid value %s for 'parse' \n " , parse ) ;
goto error ;
}
}
2002-09-05 14:52:10 +04:00
/*
* Check the URL and remove any fragment identifier
*/
2023-12-22 23:38:50 +03:00
res = xmlParseURISafe ( ( const char * ) href , & uri ) ;
2002-09-05 14:52:10 +04:00
if ( uri = = NULL ) {
2023-12-10 20:15:59 +03:00
if ( res < 0 )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
else
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_HREF_URI ,
2023-12-22 23:38:50 +03:00
" invalid value href %s \n " , href ) ;
goto error ;
2002-09-05 14:52:10 +04:00
}
2003-12-09 14:35:37 +03:00
2002-09-05 14:52:10 +04:00
if ( uri - > fragment ! = NULL ) {
2003-12-09 14:35:37 +03:00
if ( ctxt - > legacy ! = 0 ) {
if ( fragment = = NULL ) {
fragment = ( xmlChar * ) uri - > fragment ;
} else {
xmlFree ( uri - > fragment ) ;
}
} else {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_FRAGMENT_ID ,
" Invalid fragment identifier in URI %s use the xpointer attribute \n " ,
2023-12-22 23:38:50 +03:00
href ) ;
goto error ;
2003-12-09 14:35:37 +03:00
}
2002-09-05 14:52:10 +04:00
uri - > fragment = NULL ;
}
2023-12-22 23:38:50 +03:00
tmp = xmlSaveUri ( uri ) ;
if ( tmp = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-22 23:38:50 +03:00
goto error ;
2002-09-05 14:52:10 +04:00
}
2023-12-22 23:38:50 +03:00
xmlFree ( href ) ;
href = tmp ;
/*
* Resolve URI
*/
if ( xmlNodeGetBaseSafe ( ctxt - > doc , cur , & base ) < 0 ) {
xmlXIncludeErrMemory ( ctxt ) ;
goto error ;
}
if ( href [ 0 ] ! = 0 ) {
if ( xmlBuildURISafe ( href , base , & tmp ) < 0 ) {
xmlXIncludeErrMemory ( ctxt ) ;
goto error ;
}
if ( tmp = = NULL ) {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_HREF_URI ,
" failed build URL \n " , NULL ) ;
goto error ;
}
xmlFree ( href ) ;
href = tmp ;
2002-09-05 14:52:10 +04:00
2023-12-22 23:38:50 +03:00
if ( xmlStrEqual ( href , ctxt - > doc - > URL ) )
local = 1 ;
} else {
local = 1 ;
}
2022-03-02 04:57:49 +03:00
2008-02-08 12:56:31 +03:00
/*
* If local and xml then we need a fragment
*/
if ( ( local = = 1 ) & & ( xml = = 1 ) & &
( ( fragment = = NULL ) | | ( fragment [ 0 ] = = 0 ) ) ) {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_RECURSION ,
" detected a local recursion with no xpointer in %s \n " ,
2023-12-22 23:38:50 +03:00
href ) ;
goto error ;
2008-02-08 12:56:31 +03:00
}
2023-12-22 23:38:50 +03:00
ref = ( xmlXIncludeRefPtr ) xmlMalloc ( sizeof ( xmlXIncludeRef ) ) ;
2002-09-05 14:52:10 +04:00
if ( ref = = NULL ) {
2023-12-22 23:38:50 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
goto error ;
2002-09-05 14:52:10 +04:00
}
2023-12-22 23:38:50 +03:00
memset ( ref , 0 , sizeof ( xmlXIncludeRef ) ) ;
ref - > elem = cur ;
2002-09-05 14:52:10 +04:00
ref - > xml = xml ;
2023-12-22 23:38:50 +03:00
ref - > URI = href ;
href = NULL ;
ref - > fragment = fragment ;
fragment = NULL ;
/*
* xml : base fixup
*/
if ( ( ( ctxt - > parseFlags & XML_PARSE_NOBASEFIX ) = = 0 ) & &
( cur - > doc ! = NULL ) & &
( ( cur - > doc - > parseFlags & XML_PARSE_NOBASEFIX ) = = 0 ) ) {
if ( base ! = NULL ) {
ref - > base = base ;
base = NULL ;
} else {
ref - > base = xmlStrdup ( BAD_CAST " " ) ;
2024-03-24 14:28:22 +03:00
if ( ref - > base = = NULL ) {
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-22 23:38:50 +03:00
goto error ;
2024-03-24 14:28:22 +03:00
}
2023-12-22 23:38:50 +03:00
}
}
if ( ctxt - > incNr > = ctxt - > incMax ) {
xmlXIncludeRefPtr * table ;
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
size_t newSize = ctxt - > incMax ? ctxt - > incMax * 2 : 1 ;
# else
size_t newSize = ctxt - > incMax ? ctxt - > incMax * 2 : 4 ;
# endif
table = ( xmlXIncludeRefPtr * ) xmlRealloc ( ctxt - > incTab ,
newSize * sizeof ( ctxt - > incTab [ 0 ] ) ) ;
if ( table = = NULL ) {
xmlXIncludeErrMemory ( ctxt ) ;
goto error ;
}
ctxt - > incTab = table ;
ctxt - > incMax = newSize ;
}
ctxt - > incTab [ ctxt - > incNr + + ] = ref ;
ret = ref ;
ref = NULL ;
error :
xmlXIncludeFreeRef ( ref ) ;
xmlFreeURI ( uri ) ;
xmlFree ( href ) ;
xmlFree ( parse ) ;
xmlFree ( fragment ) ;
xmlFree ( base ) ;
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
/**
2002-09-05 14:52:10 +04:00
* xmlXIncludeRecurseDoc :
2001-02-23 20:55:21 +03:00
* @ ctxt : the XInclude context
* @ doc : the new document
* @ url : the associated URL
2012-09-11 09:26:36 +04:00
*
2002-09-05 14:52:10 +04:00
* The XInclude recursive nature is handled at this point .
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static void
2023-12-22 23:38:50 +03:00
xmlXIncludeRecurseDoc ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc ) {
2022-10-23 18:52:29 +03:00
xmlDocPtr oldDoc ;
xmlXIncludeRefPtr * oldIncTab ;
2022-10-30 22:28:20 +03:00
int oldIncMax , oldIncNr , oldIsStream ;
2001-05-23 17:44:21 +04:00
int i ;
2022-10-23 18:52:29 +03:00
oldDoc = ctxt - > doc ;
oldIncMax = ctxt - > incMax ;
oldIncNr = ctxt - > incNr ;
oldIncTab = ctxt - > incTab ;
2022-10-30 22:28:20 +03:00
oldIsStream = ctxt - > isStream ;
2022-10-23 18:52:29 +03:00
ctxt - > doc = doc ;
ctxt - > incMax = 0 ;
ctxt - > incNr = 0 ;
ctxt - > incTab = NULL ;
2022-10-30 22:28:20 +03:00
ctxt - > isStream = 0 ;
2004-06-07 12:57:27 +04:00
2022-10-23 18:52:29 +03:00
xmlXIncludeDoProcess ( ctxt , xmlDocGetRootElement ( doc ) ) ;
2003-03-27 17:24:00 +03:00
2022-10-23 18:52:29 +03:00
if ( ctxt - > incTab ! = NULL ) {
for ( i = 0 ; i < ctxt - > incNr ; i + + )
xmlXIncludeFreeRef ( ctxt - > incTab [ i ] ) ;
xmlFree ( ctxt - > incTab ) ;
2001-05-23 17:44:21 +04:00
}
2022-10-23 18:52:29 +03:00
ctxt - > doc = oldDoc ;
ctxt - > incMax = oldIncMax ;
ctxt - > incNr = oldIncNr ;
ctxt - > incTab = oldIncTab ;
2022-10-30 22:28:20 +03:00
ctxt - > isStream = oldIsStream ;
2001-02-23 20:55:21 +03:00
}
2002-02-10 14:57:22 +03:00
/************************************************************************
* *
* Node copy with specific semantic *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-12-22 23:38:50 +03:00
static void
xmlXIncludeBaseFixup ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr cur , xmlNodePtr copy ,
const xmlChar * targetBase ) {
xmlChar * base = NULL ;
xmlChar * relBase = NULL ;
2024-03-30 19:17:21 +03:00
xmlNs ns ;
2023-12-22 23:38:50 +03:00
int res ;
2024-04-05 14:19:56 +03:00
if ( cur - > type ! = XML_ELEMENT_NODE )
return ;
2023-12-22 23:38:50 +03:00
if ( xmlNodeGetBaseSafe ( cur - > doc , cur , & base ) < 0 )
xmlXIncludeErrMemory ( ctxt ) ;
if ( ( base ! = NULL ) & & ! xmlStrEqual ( base , targetBase ) ) {
2024-07-01 17:01:24 +03:00
if ( ( xmlStrlen ( base ) > XML_MAX_URI_LENGTH ) | |
( xmlStrlen ( targetBase ) > XML_MAX_URI_LENGTH ) ) {
relBase = xmlStrdup ( base ) ;
if ( relBase = = NULL ) {
xmlXIncludeErrMemory ( ctxt ) ;
goto done ;
}
} else if ( xmlBuildRelativeURISafe ( base , targetBase , & relBase ) < 0 ) {
2023-12-22 23:38:50 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
goto done ;
}
if ( relBase = = NULL ) {
xmlXIncludeErr ( ctxt , cur ,
XML_XINCLUDE_HREF_URI ,
" Building relative URI failed: %s \n " ,
base ) ;
goto done ;
}
2023-12-28 18:42:03 +03:00
/*
* If the new base doesn ' t contain a slash , it can be omitted .
*/
if ( xmlStrchr ( relBase , ' / ' ) ! = NULL ) {
2023-12-22 23:38:50 +03:00
res = xmlNodeSetBase ( copy , relBase ) ;
if ( res < 0 )
xmlXIncludeErrMemory ( ctxt ) ;
goto done ;
}
}
/*
* Delete existing xml : base if bases are equal
*/
2024-03-30 19:17:21 +03:00
memset ( & ns , 0 , sizeof ( ns ) ) ;
ns . href = XML_XML_NAMESPACE ;
xmlUnsetNsProp ( copy , & ns , BAD_CAST " base " ) ;
2023-12-22 23:38:50 +03:00
done :
xmlFree ( base ) ;
xmlFree ( relBase ) ;
}
2002-02-10 14:57:22 +03:00
/**
* xmlXIncludeCopyNode :
* @ ctxt : the XInclude context
* @ elem : the element
2022-10-23 18:52:29 +03:00
* @ copyChildren : copy children instead of node if true
2012-09-11 09:26:36 +04:00
*
2022-10-22 20:08:43 +03:00
* Make a copy of the node while expanding nested XIncludes .
2022-10-22 03:17:39 +03:00
*
* Returns a node list , not a single node .
2002-02-10 14:57:22 +03:00
*/
static xmlNodePtr
2022-10-23 18:52:29 +03:00
xmlXIncludeCopyNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr elem ,
2023-12-22 23:38:50 +03:00
int copyChildren , const xmlChar * targetBase ) {
2002-02-10 14:57:22 +03:00
xmlNodePtr result = NULL ;
2022-10-22 20:08:43 +03:00
xmlNodePtr insertParent = NULL ;
xmlNodePtr insertLast = NULL ;
2022-10-23 18:52:29 +03:00
xmlNodePtr cur ;
2023-12-22 23:38:50 +03:00
xmlNodePtr item ;
int depth = 0 ;
2022-10-23 18:52:29 +03:00
if ( copyChildren ) {
cur = elem - > children ;
if ( cur = = NULL )
return ( NULL ) ;
} else {
cur = elem ;
}
2022-10-22 20:08:43 +03:00
while ( 1 ) {
xmlNodePtr copy = NULL ;
int recurse = 0 ;
if ( ( cur - > type = = XML_DOCUMENT_NODE ) | |
( cur - > type = = XML_DTD_NODE ) ) {
;
} else if ( ( cur - > type = = XML_ELEMENT_NODE ) & &
( cur - > ns ! = NULL ) & &
( xmlStrEqual ( cur - > name , XINCLUDE_NODE ) ) & &
( ( xmlStrEqual ( cur - > ns - > href , XINCLUDE_NS ) ) | |
( xmlStrEqual ( cur - > ns - > href , XINCLUDE_OLD_NS ) ) ) ) {
xmlXIncludeRefPtr ref = xmlXIncludeExpandNode ( ctxt , cur ) ;
if ( ref = = NULL )
goto error ;
/*
* TODO : Insert XML_XINCLUDE_START and XML_XINCLUDE_END nodes
*/
2023-12-22 23:38:50 +03:00
for ( item = ref - > inc ; item ! = NULL ; item = item - > next ) {
copy = xmlStaticCopyNode ( item , ctxt - > doc , insertParent , 1 ) ;
2023-12-10 20:15:59 +03:00
if ( copy = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2022-10-22 20:08:43 +03:00
goto error ;
2023-12-10 20:15:59 +03:00
}
2023-12-22 23:38:50 +03:00
if ( result = = NULL )
result = copy ;
if ( insertLast ! = NULL ) {
insertLast - > next = copy ;
copy - > prev = insertLast ;
} else if ( insertParent ! = NULL ) {
insertParent - > children = copy ;
}
insertLast = copy ;
if ( ( depth = = 0 ) & & ( targetBase ! = NULL ) )
xmlXIncludeBaseFixup ( ctxt , item , copy , targetBase ) ;
2022-10-22 20:08:43 +03:00
}
} else {
copy = xmlStaticCopyNode ( cur , ctxt - > doc , insertParent , 2 ) ;
2023-12-10 20:15:59 +03:00
if ( copy = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2022-10-22 20:08:43 +03:00
goto error ;
2023-12-10 20:15:59 +03:00
}
2022-10-22 20:08:43 +03:00
if ( result = = NULL )
result = copy ;
if ( insertLast ! = NULL ) {
insertLast - > next = copy ;
copy - > prev = insertLast ;
} else if ( insertParent ! = NULL ) {
insertParent - > children = copy ;
}
insertLast = copy ;
2023-12-22 23:38:50 +03:00
if ( ( depth = = 0 ) & & ( targetBase ! = NULL ) )
xmlXIncludeBaseFixup ( ctxt , cur , copy , targetBase ) ;
recurse = ( cur - > type ! = XML_ENTITY_REF_NODE ) & &
( cur - > children ! = NULL ) ;
2022-10-22 20:08:43 +03:00
}
2002-02-10 14:57:22 +03:00
2022-10-22 20:08:43 +03:00
if ( recurse ) {
cur = cur - > children ;
insertParent = insertLast ;
insertLast = NULL ;
2023-12-22 23:38:50 +03:00
depth + = 1 ;
2022-10-22 20:08:43 +03:00
continue ;
}
2002-02-10 14:57:22 +03:00
2022-10-23 18:52:29 +03:00
if ( cur = = elem )
return ( result ) ;
while ( cur - > next = = NULL ) {
2023-09-08 15:52:22 +03:00
if ( insertParent ! = NULL )
insertParent - > last = insertLast ;
2022-10-22 20:08:43 +03:00
cur = cur - > parent ;
2022-10-23 18:52:29 +03:00
if ( cur = = elem )
return ( result ) ;
2022-10-22 20:08:43 +03:00
insertLast = insertParent ;
insertParent = insertParent - > parent ;
2023-12-22 23:38:50 +03:00
depth - = 1 ;
2022-10-22 20:08:43 +03:00
}
cur = cur - > next ;
2002-02-10 14:57:22 +03:00
}
2022-10-22 20:08:43 +03:00
error :
xmlFreeNodeList ( result ) ;
return ( NULL ) ;
2002-02-10 14:57:22 +03:00
}
2024-06-06 23:18:05 +03:00
# ifdef LIBXML_XPTR_ENABLED
2002-02-10 14:57:22 +03:00
/**
2022-10-22 20:20:20 +03:00
* xmlXIncludeCopyXPointer :
2002-02-10 14:57:22 +03:00
* @ ctxt : the XInclude context
* @ obj : the XPointer result from the evaluation .
*
* Build a node list tree copy of the XPointer result .
* This will drop Attributes and Namespace declarations .
*
* Returns an xmlNodePtr list or NULL .
* the caller has to free the node tree .
*/
static xmlNodePtr
2023-12-22 23:38:50 +03:00
xmlXIncludeCopyXPointer ( xmlXIncludeCtxtPtr ctxt , xmlXPathObjectPtr obj ,
const xmlChar * targetBase ) {
2022-10-22 03:17:39 +03:00
xmlNodePtr list = NULL , last = NULL , copy ;
2002-02-10 14:57:22 +03:00
int i ;
2022-10-22 20:20:20 +03:00
if ( ( ctxt = = NULL ) | | ( obj = = NULL ) )
2002-02-10 14:57:22 +03:00
return ( NULL ) ;
switch ( obj - > type ) {
case XPATH_NODESET : {
xmlNodeSetPtr set = obj - > nodesetval ;
if ( set = = NULL )
2023-12-26 02:42:22 +03:00
break ;
2002-02-10 14:57:22 +03:00
for ( i = 0 ; i < set - > nodeNr ; i + + ) {
2022-10-22 18:48:25 +03:00
xmlNodePtr node ;
2002-02-10 14:57:22 +03:00
if ( set - > nodeTab [ i ] = = NULL )
continue ;
switch ( set - > nodeTab [ i ] - > type ) {
2022-10-22 18:48:25 +03:00
case XML_DOCUMENT_NODE :
case XML_HTML_DOCUMENT_NODE :
node = xmlDocGetRootElement (
( xmlDocPtr ) set - > nodeTab [ i ] ) ;
if ( node = = NULL ) {
xmlXIncludeErr ( ctxt , set - > nodeTab [ i ] ,
XML_ERR_INTERNAL_ERROR ,
2023-12-26 02:42:22 +03:00
" document without root \n " , NULL ) ;
2022-10-22 18:48:25 +03:00
continue ;
}
break ;
2023-12-26 02:42:22 +03:00
case XML_TEXT_NODE :
2002-02-10 14:57:22 +03:00
case XML_CDATA_SECTION_NODE :
case XML_ELEMENT_NODE :
case XML_PI_NODE :
case XML_COMMENT_NODE :
2022-10-22 18:48:25 +03:00
node = set - > nodeTab [ i ] ;
2002-02-10 14:57:22 +03:00
break ;
2022-10-22 18:48:25 +03:00
default :
xmlXIncludeErr ( ctxt , set - > nodeTab [ i ] ,
XML_XINCLUDE_XPTR_RESULT ,
" invalid node type in XPtr result \n " ,
NULL ) ;
2002-02-10 14:57:22 +03:00
continue ; /* for */
}
2022-10-22 03:17:39 +03:00
/*
* OPTIMIZE TODO : External documents should already be
* expanded , so xmlDocCopyNode should work as well .
* xmlXIncludeCopyNode is only required for the initial
* document .
*/
2023-12-22 23:38:50 +03:00
copy = xmlXIncludeCopyNode ( ctxt , node , 0 , targetBase ) ;
2022-10-22 03:17:39 +03:00
if ( copy = = NULL ) {
xmlFreeNodeList ( list ) ;
return ( NULL ) ;
}
if ( last = = NULL ) {
list = copy ;
} else {
while ( last - > next ! = NULL )
last = last - > next ;
copy - > prev = last ;
last - > next = copy ;
2002-02-10 14:57:22 +03:00
}
2022-10-22 03:17:39 +03:00
last = copy ;
2002-02-10 14:57:22 +03:00
}
break ;
}
default :
break ;
}
return ( list ) ;
}
2024-06-06 23:18:05 +03:00
# endif
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* XInclude I / O handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-13 14:02:08 +03:00
typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData ;
typedef xmlXIncludeMergeData * xmlXIncludeMergeDataPtr ;
struct _xmlXIncludeMergeData {
xmlDocPtr doc ;
xmlXIncludeCtxtPtr ctxt ;
} ;
2003-02-05 01:48:53 +03:00
/**
* xmlXIncludeMergeOneEntity :
* @ ent : the entity
* @ doc : the including doc
2022-10-23 14:57:33 +03:00
* @ name : the entity name
2003-02-05 01:48:53 +03:00
*
2019-09-30 18:04:54 +03:00
* Implements the merge of one entity
2003-02-05 01:48:53 +03:00
*/
static void
2017-11-09 18:42:47 +03:00
xmlXIncludeMergeEntity ( void * payload , void * vdata ,
const xmlChar * name ATTRIBUTE_UNUSED ) {
xmlEntityPtr ent = ( xmlEntityPtr ) payload ;
xmlXIncludeMergeDataPtr data = ( xmlXIncludeMergeDataPtr ) vdata ;
2003-02-13 14:02:08 +03:00
xmlEntityPtr ret , prev ;
xmlDocPtr doc ;
xmlXIncludeCtxtPtr ctxt ;
2003-02-05 01:48:53 +03:00
2003-02-13 14:02:08 +03:00
if ( ( ent = = NULL ) | | ( data = = NULL ) )
return ;
ctxt = data - > ctxt ;
doc = data - > doc ;
if ( ( ctxt = = NULL ) | | ( doc = = NULL ) )
2003-02-05 01:48:53 +03:00
return ;
2003-02-13 14:02:08 +03:00
switch ( ent - > etype ) {
case XML_INTERNAL_PARAMETER_ENTITY :
case XML_EXTERNAL_PARAMETER_ENTITY :
case XML_INTERNAL_PREDEFINED_ENTITY :
return ;
case XML_INTERNAL_GENERAL_ENTITY :
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
break ;
}
2023-12-10 20:15:59 +03:00
prev = xmlGetDocEntity ( doc , ent - > name ) ;
if ( prev = = NULL ) {
ret = xmlAddDocEntity ( doc , ent - > name , ent - > etype , ent - > ExternalID ,
ent - > SystemID , ent - > content ) ;
if ( ret = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
return ;
}
if ( ent - > URI ! = NULL ) {
2003-02-05 01:48:53 +03:00
ret - > URI = xmlStrdup ( ent - > URI ) ;
2023-12-10 20:15:59 +03:00
if ( ret - > URI = = 0 )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
}
2003-02-13 14:02:08 +03:00
} else {
2023-12-10 20:15:59 +03:00
if ( ent - > etype ! = prev - > etype )
goto error ;
2003-02-13 14:02:08 +03:00
2023-12-10 20:15:59 +03:00
if ( ( ent - > SystemID ! = NULL ) & & ( prev - > SystemID ! = NULL ) ) {
if ( ! xmlStrEqual ( ent - > SystemID , prev - > SystemID ) )
goto error ;
} else if ( ( ent - > ExternalID ! = NULL ) & &
( prev - > ExternalID ! = NULL ) ) {
if ( ! xmlStrEqual ( ent - > ExternalID , prev - > ExternalID ) )
goto error ;
} else if ( ( ent - > content ! = NULL ) & & ( prev - > content ! = NULL ) ) {
if ( ! xmlStrEqual ( ent - > content , prev - > content ) )
goto error ;
} else {
goto error ;
}
2003-02-05 01:48:53 +03:00
}
2003-02-13 14:02:08 +03:00
return ;
error :
2003-03-31 20:09:37 +04:00
switch ( ent - > etype ) {
case XML_INTERNAL_PARAMETER_ENTITY :
case XML_EXTERNAL_PARAMETER_ENTITY :
case XML_INTERNAL_PREDEFINED_ENTITY :
case XML_INTERNAL_GENERAL_ENTITY :
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
return ;
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
break ;
}
2003-10-09 02:38:13 +04:00
xmlXIncludeErr ( ctxt , ( xmlNodePtr ) ent , XML_XINCLUDE_ENTITY_DEF_MISMATCH ,
" mismatch in redefinition of entity %s \n " ,
ent - > name ) ;
2003-02-05 01:48:53 +03:00
}
/**
* xmlXIncludeMergeEntities :
* @ ctxt : an XInclude context
* @ doc : the including doc
* @ from : the included doc
*
2019-09-30 18:04:54 +03:00
* Implements the entity merge
2003-02-05 01:48:53 +03:00
*
* Returns 0 if merge succeeded , - 1 if some processing failed
*/
static int
xmlXIncludeMergeEntities ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc ,
xmlDocPtr from ) {
xmlNodePtr cur ;
xmlDtdPtr target , source ;
if ( ctxt = = NULL )
return ( - 1 ) ;
if ( ( from = = NULL ) | | ( from - > intSubset = = NULL ) )
return ( 0 ) ;
target = doc - > intSubset ;
if ( target = = NULL ) {
cur = xmlDocGetRootElement ( doc ) ;
if ( cur = = NULL )
return ( - 1 ) ;
target = xmlCreateIntSubset ( doc , cur - > name , NULL , NULL ) ;
2024-04-27 17:31:01 +03:00
if ( target = = NULL ) {
xmlXIncludeErrMemory ( ctxt ) ;
2003-02-05 01:48:53 +03:00
return ( - 1 ) ;
2024-04-27 17:31:01 +03:00
}
2003-02-05 01:48:53 +03:00
}
source = from - > intSubset ;
if ( ( source ! = NULL ) & & ( source - > entities ! = NULL ) ) {
2003-02-13 14:02:08 +03:00
xmlXIncludeMergeData data ;
data . ctxt = ctxt ;
data . doc = doc ;
2003-02-05 01:48:53 +03:00
xmlHashScan ( ( xmlHashTablePtr ) source - > entities ,
2017-11-09 18:42:47 +03:00
xmlXIncludeMergeEntity , & data ) ;
2003-02-05 01:48:53 +03:00
}
source = from - > extSubset ;
if ( ( source ! = NULL ) & & ( source - > entities ! = NULL ) ) {
2003-02-13 14:02:08 +03:00
xmlXIncludeMergeData data ;
data . ctxt = ctxt ;
data . doc = doc ;
2003-02-05 01:48:53 +03:00
/*
* don ' t duplicate existing stuff when external subsets are the same
*/
if ( ( ! xmlStrEqual ( target - > ExternalID , source - > ExternalID ) ) & &
( ! xmlStrEqual ( target - > SystemID , source - > SystemID ) ) ) {
xmlHashScan ( ( xmlHashTablePtr ) source - > entities ,
2017-11-09 18:42:47 +03:00
xmlXIncludeMergeEntity , & data ) ;
2003-02-05 01:48:53 +03:00
}
}
return ( 0 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlXIncludeLoadDoc :
* @ ctxt : the XInclude context
* @ url : the associated URL
2022-10-23 14:57:33 +03:00
* @ ref : an XMLXincludeRefPtr
2012-09-11 09:26:36 +04:00
*
2001-02-23 20:55:21 +03:00
* Load the document , and store the result in the XInclude context
2002-08-14 18:11:30 +04:00
*
* Returns 0 in case of success , - 1 in case of failure
2001-02-23 20:55:21 +03:00
*/
2002-08-14 18:11:30 +04:00
static int
2023-12-22 23:38:50 +03:00
xmlXIncludeLoadDoc ( xmlXIncludeCtxtPtr ctxt , xmlXIncludeRefPtr ref ) {
2022-10-23 17:02:48 +03:00
xmlXIncludeDocPtr cache ;
2001-02-23 20:55:21 +03:00
xmlDocPtr doc ;
2023-12-22 23:38:50 +03:00
const xmlChar * url = ref - > URI ;
const xmlChar * fragment = ref - > fragment ;
2002-09-05 14:52:10 +04:00
int i = 0 ;
2022-10-30 14:32:14 +03:00
int ret = - 1 ;
2023-05-08 17:45:28 +03:00
int cacheNr ;
2004-03-08 17:42:31 +03:00
# ifdef LIBXML_XPTR_ENABLED
int saveFlags ;
# endif
2002-09-05 14:52:10 +04:00
2001-02-23 20:55:21 +03:00
/*
* Handling of references to the local document are done
* directly through ctxt - > doc .
*/
2023-12-22 23:38:50 +03:00
if ( ( url [ 0 ] = = 0 ) | | ( url [ 0 ] = = ' # ' ) | |
( ( ctxt - > doc ! = NULL ) & & ( xmlStrEqual ( url , ctxt - > doc - > URL ) ) ) ) {
2022-10-21 16:56:12 +03:00
doc = ctxt - > doc ;
2001-02-23 20:55:21 +03:00
goto loaded ;
}
/*
2022-10-23 17:02:48 +03:00
* Prevent reloading the document twice .
2001-02-23 20:55:21 +03:00
*/
2022-10-23 18:52:29 +03:00
for ( i = 0 ; i < ctxt - > urlNr ; i + + ) {
2023-12-22 23:38:50 +03:00
if ( xmlStrEqual ( url , ctxt - > urlTab [ i ] . url ) ) {
2022-10-23 18:52:29 +03:00
if ( ctxt - > urlTab [ i ] . expanding ) {
2022-10-23 17:02:48 +03:00
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_RECURSION ,
" inclusion loop detected \n " , NULL ) ;
2022-10-30 14:32:14 +03:00
goto error ;
2022-10-23 17:02:48 +03:00
}
2022-10-23 18:52:29 +03:00
doc = ctxt - > urlTab [ i ] . doc ;
2022-10-30 14:32:14 +03:00
if ( doc = = NULL )
goto error ;
2001-02-23 20:55:21 +03:00
goto loaded ;
}
}
2002-09-05 14:52:10 +04:00
2001-02-23 20:55:21 +03:00
/*
* Load it .
*/
2004-03-08 17:42:31 +03:00
# ifdef LIBXML_XPTR_ENABLED
/*
* If this is an XPointer evaluation , we want to assure that
* all entities have been resolved prior to processing the
* referenced document
*/
saveFlags = ctxt - > parseFlags ;
if ( fragment ! = NULL ) { /* if this is an XPointer eval */
ctxt - > parseFlags | = XML_PARSE_NOENT ;
}
# endif
2023-12-22 23:38:50 +03:00
doc = xmlXIncludeParseFile ( ctxt , ( const char * ) url ) ;
2004-03-08 17:42:31 +03:00
# ifdef LIBXML_XPTR_ENABLED
ctxt - > parseFlags = saveFlags ;
# endif
2022-10-23 17:02:48 +03:00
/* Also cache NULL docs */
2022-10-23 18:52:29 +03:00
if ( ctxt - > urlNr > = ctxt - > urlMax ) {
2022-10-23 17:02:48 +03:00
xmlXIncludeDoc * tmp ;
2023-05-08 18:05:13 +03:00
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
size_t newSize = ctxt - > urlMax ? ctxt - > urlMax * 2 : 1 ;
# else
2022-10-23 18:52:29 +03:00
size_t newSize = ctxt - > urlMax ? ctxt - > urlMax * 2 : 8 ;
2023-05-08 18:05:13 +03:00
# endif
2022-10-23 17:02:48 +03:00
2022-10-23 18:52:29 +03:00
tmp = xmlRealloc ( ctxt - > urlTab , sizeof ( xmlXIncludeDoc ) * newSize ) ;
2022-10-23 17:02:48 +03:00
if ( tmp = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-02-16 14:10:36 +03:00
xmlFreeDoc ( doc ) ;
2022-10-30 14:32:14 +03:00
goto error ;
2022-10-23 17:02:48 +03:00
}
2022-10-23 18:52:29 +03:00
ctxt - > urlMax = newSize ;
ctxt - > urlTab = tmp ;
2022-10-23 17:02:48 +03:00
}
2023-12-10 20:15:59 +03:00
cache = & ctxt - > urlTab [ ctxt - > urlNr ] ;
2022-10-23 17:02:48 +03:00
cache - > doc = doc ;
2023-12-22 23:38:50 +03:00
cache - > url = xmlStrdup ( url ) ;
2023-12-10 20:15:59 +03:00
if ( cache - > url = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
xmlFreeDoc ( doc ) ;
goto error ;
}
2022-10-23 17:02:48 +03:00
cache - > expanding = 0 ;
2023-12-10 20:15:59 +03:00
cacheNr = ctxt - > urlNr + + ;
2022-10-23 17:02:48 +03:00
2022-10-30 14:32:14 +03:00
if ( doc = = NULL )
goto error ;
2004-07-26 04:20:13 +04:00
/*
* It ' s possible that the requested URL has been mapped to a
* completely different location ( e . g . through a catalog entry ) .
* To check for this , we compare the URL with that of the doc
* and change it if they disagree ( bug 146988 ) .
*/
2023-12-22 23:38:50 +03:00
if ( ( doc - > URL ! = NULL ) & & ( ! xmlStrEqual ( url , doc - > URL ) ) )
url = doc - > URL ;
2002-09-05 14:52:10 +04:00
/*
2003-02-05 01:48:53 +03:00
* Make sure we have all entities fixed up
2002-09-05 14:52:10 +04:00
*/
2003-02-05 01:48:53 +03:00
xmlXIncludeMergeEntities ( ctxt , ctxt - > doc , doc ) ;
2002-09-05 14:52:10 +04:00
/*
* We don ' t need the DTD anymore , free up space
if ( doc - > intSubset ! = NULL ) {
xmlUnlinkNode ( ( xmlNodePtr ) doc - > intSubset ) ;
xmlFreeNode ( ( xmlNodePtr ) doc - > intSubset ) ;
doc - > intSubset = NULL ;
}
if ( doc - > extSubset ! = NULL ) {
xmlUnlinkNode ( ( xmlNodePtr ) doc - > extSubset ) ;
xmlFreeNode ( ( xmlNodePtr ) doc - > extSubset ) ;
doc - > extSubset = NULL ;
}
*/
2022-10-23 17:02:48 +03:00
cache - > expanding = 1 ;
2023-12-22 23:38:50 +03:00
xmlXIncludeRecurseDoc ( ctxt , doc ) ;
2023-05-08 17:45:28 +03:00
/* urlTab might be reallocated. */
cache = & ctxt - > urlTab [ cacheNr ] ;
2022-10-23 17:02:48 +03:00
cache - > expanding = 0 ;
2001-02-23 20:55:21 +03:00
loaded :
if ( fragment = = NULL ) {
2023-12-22 23:38:50 +03:00
xmlNodePtr root ;
root = xmlDocGetRootElement ( doc ) ;
if ( root = = NULL ) {
xmlXIncludeErr ( ctxt , ref - > elem , XML_ERR_INTERNAL_ERROR ,
" document without root \n " , NULL ) ;
goto error ;
}
ref - > inc = xmlDocCopyNode ( root , ctxt - > doc , 1 ) ;
2023-12-10 20:15:59 +03:00
if ( ref - > inc = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-22 23:38:50 +03:00
goto error ;
2023-12-10 20:15:59 +03:00
}
2023-12-22 23:38:50 +03:00
if ( ref - > base ! = NULL )
xmlXIncludeBaseFixup ( ctxt , root , ref - > inc , ref - > base ) ;
2012-09-11 09:26:36 +04:00
}
2003-09-02 00:59:40 +04:00
# ifdef LIBXML_XPTR_ENABLED
else {
2001-02-23 20:55:21 +03:00
/*
* Computes the XPointer expression and make a copy used
* as the replacement copy .
*/
xmlXPathObjectPtr xptr ;
2001-06-19 22:09:42 +04:00
xmlNodeSetPtr set ;
2001-02-23 20:55:21 +03:00
2022-10-30 22:28:20 +03:00
if ( ctxt - > isStream & & doc = = ctxt - > doc ) {
2022-10-30 14:21:20 +03:00
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_XPTR_FAILED ,
" XPointer expressions not allowed in streaming "
" mode \n " , NULL ) ;
2022-10-30 14:32:14 +03:00
goto error ;
2022-10-30 14:21:20 +03:00
}
2023-12-10 20:15:59 +03:00
if ( ctxt - > xpctxt = = NULL ) {
2024-06-12 19:20:01 +03:00
ctxt - > xpctxt = xmlXPathNewContext ( doc ) ;
2023-12-10 20:15:59 +03:00
if ( ctxt - > xpctxt = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
goto error ;
}
2023-12-18 21:43:55 +03:00
if ( ctxt - > errorHandler ! = NULL )
xmlXPathSetErrorHandler ( ctxt - > xpctxt , ctxt - > errorHandler ,
ctxt - > errorCtxt ) ;
2023-12-10 20:15:59 +03:00
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ctxt - > xpctxt - > opLimit = 100000 ;
# endif
2024-06-17 15:15:49 +03:00
} else {
ctxt - > xpctxt - > doc = doc ;
2023-12-10 20:15:59 +03:00
}
xptr = xmlXPtrEval ( fragment , ctxt - > xpctxt ) ;
2024-06-14 21:44:45 +03:00
if ( ctxt - > xpctxt - > lastError . code ! = XML_ERR_OK ) {
2023-12-10 20:15:59 +03:00
if ( ctxt - > xpctxt - > lastError . code = = XML_ERR_NO_MEMORY )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
else
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_XPTR_FAILED ,
" XPointer evaluation failed: #%s \n " ,
fragment ) ;
2022-10-30 14:32:14 +03:00
goto error ;
2001-02-23 20:55:21 +03:00
}
2024-06-14 21:44:45 +03:00
if ( xptr = = NULL )
goto done ;
2001-06-19 22:09:42 +04:00
switch ( xptr - > type ) {
case XPATH_UNDEFINED :
case XPATH_BOOLEAN :
case XPATH_NUMBER :
case XPATH_STRING :
case XPATH_USERS :
case XPATH_XSLT_TREE :
2022-10-23 14:57:33 +03:00
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_XPTR_RESULT ,
2003-10-09 02:38:13 +04:00
" XPointer is not a range: #%s \n " ,
fragment ) ;
2020-05-30 16:32:25 +03:00
xmlXPathFreeObject ( xptr ) ;
2022-10-30 14:32:14 +03:00
goto error ;
2001-06-19 22:09:42 +04:00
case XPATH_NODESET :
2023-12-26 02:42:22 +03:00
break ;
2004-06-08 06:01:28 +04:00
2001-06-19 22:09:42 +04:00
}
set = xptr - > nodesetval ;
if ( set ! = NULL ) {
for ( i = 0 ; i < set - > nodeNr ; i + + ) {
if ( set - > nodeTab [ i ] = = NULL )
continue ;
switch ( set - > nodeTab [ i ] - > type ) {
2007-07-18 22:04:55 +04:00
case XML_ELEMENT_NODE :
2001-06-19 22:09:42 +04:00
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
case XML_ENTITY_REF_NODE :
case XML_ENTITY_NODE :
case XML_PI_NODE :
case XML_COMMENT_NODE :
case XML_DOCUMENT_NODE :
case XML_HTML_DOCUMENT_NODE :
continue ;
2004-06-08 06:01:28 +04:00
2001-06-19 22:09:42 +04:00
case XML_ATTRIBUTE_NODE :
2022-10-23 14:57:33 +03:00
xmlXIncludeErr ( ctxt , ref - > elem ,
2003-10-09 02:38:13 +04:00
XML_XINCLUDE_XPTR_RESULT ,
" XPointer selects an attribute: #%s \n " ,
fragment ) ;
2001-06-19 22:09:42 +04:00
set - > nodeTab [ i ] = NULL ;
continue ;
case XML_NAMESPACE_DECL :
2022-10-23 14:57:33 +03:00
xmlXIncludeErr ( ctxt , ref - > elem ,
2003-10-09 02:38:13 +04:00
XML_XINCLUDE_XPTR_RESULT ,
" XPointer selects a namespace: #%s \n " ,
fragment ) ;
2001-06-19 22:09:42 +04:00
set - > nodeTab [ i ] = NULL ;
continue ;
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
case XML_NOTATION_NODE :
case XML_DTD_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2022-10-23 14:57:33 +03:00
xmlXIncludeErr ( ctxt , ref - > elem ,
2003-10-09 02:38:13 +04:00
XML_XINCLUDE_XPTR_RESULT ,
" XPointer selects unexpected nodes: #%s \n " ,
fragment ) ;
2001-06-19 22:09:42 +04:00
set - > nodeTab [ i ] = NULL ;
set - > nodeTab [ i ] = NULL ;
continue ; /* for */
}
}
}
2023-12-22 23:38:50 +03:00
ref - > inc = xmlXIncludeCopyXPointer ( ctxt , xptr , ref - > base ) ;
2022-10-21 16:56:12 +03:00
xmlXPathFreeObject ( xptr ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-02 00:59:40 +04:00
# endif
2002-08-14 18:45:25 +04:00
2024-06-14 21:44:45 +03:00
done :
2022-10-30 14:32:14 +03:00
ret = 0 ;
error :
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlXIncludeLoadTxt :
* @ ctxt : the XInclude context
2022-10-23 14:57:33 +03:00
* @ ref : an XMLXincludeRefPtr
2012-09-11 09:26:36 +04:00
*
2001-02-23 20:55:21 +03:00
* Load the content , and store the result in the XInclude context
2002-08-14 18:11:30 +04:00
*
* Returns 0 in case of success , - 1 in case of failure
2001-02-23 20:55:21 +03:00
*/
2002-08-14 18:11:30 +04:00
static int
2023-12-22 23:38:50 +03:00
xmlXIncludeLoadTxt ( xmlXIncludeCtxtPtr ctxt , xmlXIncludeRefPtr ref ) {
2001-02-23 20:55:21 +03:00
xmlParserInputBufferPtr buf ;
2023-02-16 14:40:02 +03:00
xmlNodePtr node = NULL ;
2023-12-22 23:38:50 +03:00
const xmlChar * url = ref - > URI ;
2001-02-23 20:55:21 +03:00
int i ;
2023-02-16 14:40:02 +03:00
int ret = - 1 ;
2002-11-20 16:28:31 +03:00
xmlChar * encoding = NULL ;
2023-12-10 20:15:59 +03:00
xmlCharEncodingHandlerPtr handler = NULL ;
2023-02-16 14:40:02 +03:00
xmlParserCtxtPtr pctxt = NULL ;
xmlParserInputPtr inputStream = NULL ;
2023-02-13 16:38:05 +03:00
int len ;
2023-12-10 20:15:59 +03:00
int res ;
2023-02-13 16:38:05 +03:00
const xmlChar * content ;
2001-02-23 20:55:21 +03:00
/*
* Handling of references to the local document are done
* directly through ctxt - > doc .
*/
2023-12-22 23:38:50 +03:00
if ( url [ 0 ] = = 0 ) {
2022-10-23 14:57:33 +03:00
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_TEXT_DOCUMENT ,
2003-10-09 02:38:13 +04:00
" text serialization of document not available \n " , NULL ) ;
2023-02-16 14:40:02 +03:00
goto error ;
2001-02-23 20:55:21 +03:00
}
/*
2022-10-23 17:02:48 +03:00
* Prevent reloading the document twice .
2001-02-23 20:55:21 +03:00
*/
2022-10-23 18:52:29 +03:00
for ( i = 0 ; i < ctxt - > txtNr ; i + + ) {
2023-12-22 23:38:50 +03:00
if ( xmlStrEqual ( url , ctxt - > txtTab [ i ] . url ) ) {
2022-10-23 17:02:48 +03:00
node = xmlNewDocText ( ctxt - > doc , ctxt - > txtTab [ i ] . text ) ;
2023-12-10 20:15:59 +03:00
if ( node = = NULL )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2001-02-23 20:55:21 +03:00
goto loaded ;
}
}
2022-10-23 17:02:48 +03:00
2002-11-20 16:28:31 +03:00
/*
* Try to get the encoding if available
*/
2022-10-23 14:57:33 +03:00
if ( ref - > elem ! = NULL ) {
2023-12-10 20:15:59 +03:00
encoding = xmlXIncludeGetProp ( ctxt , ref - > elem , XINCLUDE_PARSE_ENCODING ) ;
2002-11-20 16:28:31 +03:00
}
if ( encoding ! = NULL ) {
2024-01-02 20:33:57 +03:00
res = xmlOpenCharEncodingHandler ( ( const char * ) encoding ,
/* output */ 0 , & handler ) ;
2023-12-10 20:15:59 +03:00
if ( res ! = 0 ) {
if ( res = = XML_ERR_NO_MEMORY ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
} else if ( res = = XML_ERR_UNSUPPORTED_ENCODING ) {
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_UNKNOWN_ENCODING ,
" encoding %s not supported \n " , encoding ) ;
goto error ;
} else {
xmlXIncludeErr ( ctxt , ref - > elem , res ,
" unexpected error from iconv or ICU \n " , NULL ) ;
goto error ;
}
}
2002-11-20 16:28:31 +03:00
}
2001-02-23 20:55:21 +03:00
/*
* Load it .
*/
2012-05-10 16:59:33 +04:00
pctxt = xmlNewParserCtxt ( ) ;
2023-12-10 20:15:59 +03:00
if ( pctxt = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
goto error ;
}
2024-06-11 15:40:28 +03:00
if ( ctxt - > errorHandler ! = NULL )
xmlCtxtSetErrorHandler ( pctxt , ctxt - > errorHandler , ctxt - > errorCtxt ) ;
if ( ctxt - > resourceLoader ! = NULL )
xmlCtxtSetResourceLoader ( pctxt , ctxt - > resourceLoader ,
ctxt - > resourceCtxt ) ;
2024-06-11 20:10:41 +03:00
inputStream = xmlLoadResource ( pctxt , ( const char * ) url , NULL ,
XML_RESOURCE_XINCLUDE_TEXT ) ;
2023-12-10 20:15:59 +03:00
if ( inputStream = = NULL ) {
2024-07-18 20:27:43 +03:00
/*
* ENOENT only produces a warning which isn ' t reflected in errNo .
*/
2023-12-10 20:15:59 +03:00
if ( pctxt - > errNo = = XML_ERR_NO_MEMORY )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2024-07-18 20:27:43 +03:00
else if ( ( pctxt - > errNo ! = XML_ERR_OK ) & &
( pctxt - > errNo ! = XML_IO_ENOENT ) & &
( pctxt - > errNo ! = XML_IO_UNKNOWN ) )
2023-12-10 20:15:59 +03:00
xmlXIncludeErr ( ctxt , NULL , pctxt - > errNo , " load error " , NULL ) ;
2023-02-16 14:40:02 +03:00
goto error ;
2023-12-10 20:15:59 +03:00
}
2012-05-10 16:59:33 +04:00
buf = inputStream - > buf ;
2023-02-16 14:40:02 +03:00
if ( buf = = NULL )
goto error ;
2012-05-10 16:59:33 +04:00
if ( buf - > encoder )
xmlCharEncCloseFunc ( buf - > encoder ) ;
2023-12-10 20:15:59 +03:00
buf - > encoder = handler ;
handler = NULL ;
2022-05-21 00:28:25 +03:00
node = xmlNewDocText ( ctxt - > doc , NULL ) ;
2023-02-04 17:00:54 +03:00
if ( node = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-02-16 14:40:02 +03:00
goto error ;
2023-02-04 17:00:54 +03:00
}
2001-02-23 20:55:21 +03:00
/*
* Scan all chars from the resource and add the to the node
*/
2023-12-10 20:15:59 +03:00
do {
res = xmlParserInputBufferRead ( buf , 4096 ) ;
} while ( res > 0 ) ;
if ( res < 0 ) {
if ( buf - > error = = XML_ERR_NO_MEMORY )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
else
xmlXIncludeErr ( ctxt , NULL , buf - > error , " read error " , NULL ) ;
goto error ;
}
2023-02-13 16:38:05 +03:00
content = xmlBufContent ( buf - > buffer ) ;
2024-07-07 04:01:51 +03:00
len = xmlBufUse ( buf - > buffer ) ;
2023-02-13 16:38:05 +03:00
for ( i = 0 ; i < len ; ) {
int cur ;
int l ;
2023-09-22 16:45:20 +03:00
l = len - i ;
cur = xmlGetUTF8Char ( & content [ i ] , & l ) ;
if ( ( cur < 0 ) | | ( ! IS_CHAR ( cur ) ) ) {
2023-02-13 16:38:05 +03:00
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_INVALID_CHAR ,
2023-12-22 23:38:50 +03:00
" %s contains invalid char \n " , url ) ;
2023-02-16 14:40:02 +03:00
goto error ;
2023-02-13 16:38:05 +03:00
}
i + = l ;
2001-02-23 20:55:21 +03:00
}
2023-02-13 16:38:05 +03:00
2023-12-10 20:15:59 +03:00
if ( xmlNodeAddContentLen ( node , content , len ) < 0 )
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2001-02-23 20:55:21 +03:00
2022-10-23 18:52:29 +03:00
if ( ctxt - > txtNr > = ctxt - > txtMax ) {
2022-10-23 17:02:48 +03:00
xmlXIncludeTxt * tmp ;
2023-05-08 18:05:13 +03:00
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
size_t newSize = ctxt - > txtMax ? ctxt - > txtMax * 2 : 1 ;
# else
2022-10-23 18:52:29 +03:00
size_t newSize = ctxt - > txtMax ? ctxt - > txtMax * 2 : 8 ;
2023-05-08 18:05:13 +03:00
# endif
2022-10-23 17:02:48 +03:00
2022-10-23 18:52:29 +03:00
tmp = xmlRealloc ( ctxt - > txtTab , sizeof ( xmlXIncludeTxt ) * newSize ) ;
2022-10-23 17:02:48 +03:00
if ( tmp = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-02-16 14:40:02 +03:00
goto error ;
2022-10-23 17:02:48 +03:00
}
2022-10-23 18:52:29 +03:00
ctxt - > txtMax = newSize ;
ctxt - > txtTab = tmp ;
2022-10-23 17:02:48 +03:00
}
2022-10-23 18:52:29 +03:00
ctxt - > txtTab [ ctxt - > txtNr ] . text = xmlStrdup ( node - > content ) ;
2023-12-10 20:15:59 +03:00
if ( ( node - > content ! = NULL ) & &
( ctxt - > txtTab [ ctxt - > txtNr ] . text = = NULL ) ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
goto error ;
}
2023-12-22 23:38:50 +03:00
ctxt - > txtTab [ ctxt - > txtNr ] . url = xmlStrdup ( url ) ;
2023-12-10 20:15:59 +03:00
if ( ctxt - > txtTab [ ctxt - > txtNr ] . url = = NULL ) {
2023-12-18 21:43:55 +03:00
xmlXIncludeErrMemory ( ctxt ) ;
2023-12-10 20:15:59 +03:00
xmlFree ( ctxt - > txtTab [ ctxt - > txtNr ] . text ) ;
goto error ;
}
2022-10-23 18:52:29 +03:00
ctxt - > txtNr + + ;
2022-10-23 17:02:48 +03:00
2001-02-23 20:55:21 +03:00
loaded :
/*
* Add the element as the replacement copy .
*/
2022-10-23 14:57:33 +03:00
ref - > inc = node ;
2023-02-16 14:40:02 +03:00
node = NULL ;
ret = 0 ;
error :
xmlFreeNode ( node ) ;
xmlFreeInputStream ( inputStream ) ;
xmlFreeParserCtxt ( pctxt ) ;
2023-12-10 20:15:59 +03:00
xmlCharEncCloseFunc ( handler ) ;
2023-02-16 14:40:02 +03:00
xmlFree ( encoding ) ;
return ( ret ) ;
2002-08-14 18:11:30 +04:00
}
/**
* xmlXIncludeLoadFallback :
* @ ctxt : the XInclude context
* @ fallback : the fallback node
2022-10-23 14:57:33 +03:00
* @ ref : an XMLXincludeRefPtr
2012-09-11 09:26:36 +04:00
*
2002-09-05 14:52:10 +04:00
* Load the content of the fallback node , and store the result
2002-08-14 18:11:30 +04:00
* in the XInclude context
*
* Returns 0 in case of success , - 1 in case of failure
*/
static int
2022-10-23 14:57:33 +03:00
xmlXIncludeLoadFallback ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr fallback ,
xmlXIncludeRefPtr ref ) {
2004-01-02 17:59:41 +03:00
int ret = 0 ;
2022-10-23 18:52:29 +03:00
int oldNbErrors ;
2012-08-09 10:24:02 +04:00
if ( ( fallback = = NULL ) | | ( fallback - > type = = XML_NAMESPACE_DECL ) | |
( ctxt = = NULL ) )
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2004-02-06 12:33:59 +03:00
if ( fallback - > children ! = NULL ) {
/*
* It ' s possible that the fallback also has ' includes '
* ( Bug 129969 ) , so we re - process the fallback just in case
*/
2022-10-23 18:52:29 +03:00
oldNbErrors = ctxt - > nbErrors ;
2023-12-22 23:38:50 +03:00
ref - > inc = xmlXIncludeCopyNode ( ctxt , fallback , 1 , ref - > base ) ;
2019-09-13 16:45:21 +03:00
if ( ctxt - > nbErrors > oldNbErrors )
2004-02-06 12:33:59 +03:00
ret = - 1 ;
} else {
2022-10-23 14:57:33 +03:00
ref - > inc = NULL ;
2004-02-06 12:33:59 +03:00
}
2022-10-23 14:57:33 +03:00
ref - > fallback = 1 ;
2004-01-02 17:59:41 +03:00
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
/************************************************************************
* *
* XInclude Processing *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
2022-10-21 17:17:48 +03:00
* xmlXIncludeExpandNode :
2001-02-23 20:55:21 +03:00
* @ ctxt : an XInclude context
* @ node : an XInclude node
*
2022-10-21 17:17:48 +03:00
* If the XInclude node wasn ' t processed yet , create a new RefPtr ,
* add it to ctxt - > incTab and load the included items .
2001-02-23 20:55:21 +03:00
*
2022-10-21 17:17:48 +03:00
* Returns the new or existing xmlXIncludeRefPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
2022-10-21 17:17:48 +03:00
static xmlXIncludeRefPtr
xmlXIncludeExpandNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
2022-10-23 14:57:33 +03:00
xmlXIncludeRefPtr ref ;
int i ;
2022-10-21 17:17:48 +03:00
2023-02-03 16:37:49 +03:00
if ( ctxt - > fatalErr )
return ( NULL ) ;
2022-10-22 17:50:18 +03:00
if ( ctxt - > depth > = XINCLUDE_MAX_DEPTH ) {
xmlXIncludeErr ( ctxt , node , XML_XINCLUDE_RECURSION ,
" maximum recursion depth exceeded \n " , NULL ) ;
2023-02-03 16:37:49 +03:00
ctxt - > fatalErr = 1 ;
2022-10-22 17:50:18 +03:00
return ( NULL ) ;
}
2023-02-03 16:55:53 +03:00
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/*
* The XInclude engine offers no protection against exponential
* expansion attacks similar to " billion laughs " . Avoid timeouts by
* limiting the total number of replacements when fuzzing .
2023-09-30 16:47:46 +03:00
*
* Unfortuately , a single XInclude can already result in quadratic
* behavior :
*
* < doc xmlns : xi = " http://www.w3.org/2001/XInclude " >
* < xi : include xpointer = " xpointer(//e) " / >
* < e >
* < e >
* < e >
* < ! - - more nested elements - - >
* < / e >
* < / e >
* < / e >
* < / doc >
2023-02-03 16:55:53 +03:00
*/
if ( ctxt - > incTotal > = 20 )
return ( NULL ) ;
ctxt - > incTotal + + ;
# endif
2022-10-23 18:52:29 +03:00
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
2022-10-23 14:57:33 +03:00
if ( ctxt - > incTab [ i ] - > elem = = node ) {
2022-10-22 17:09:21 +03:00
if ( ctxt - > incTab [ i ] - > expanding ) {
xmlXIncludeErr ( ctxt , node , XML_XINCLUDE_RECURSION ,
" inclusion loop detected \n " , NULL ) ;
return ( NULL ) ;
}
2022-10-21 17:17:48 +03:00
return ( ctxt - > incTab [ i ] ) ;
2022-10-22 17:09:21 +03:00
}
2022-10-21 17:17:48 +03:00
}
2022-10-23 14:57:33 +03:00
ref = xmlXIncludeAddNode ( ctxt , node ) ;
if ( ref = = NULL )
2022-10-21 17:17:48 +03:00
return ( NULL ) ;
2022-10-23 14:57:33 +03:00
ref - > expanding = 1 ;
2022-10-22 17:50:18 +03:00
ctxt - > depth + + ;
2022-10-23 14:57:33 +03:00
xmlXIncludeLoadNode ( ctxt , ref ) ;
2022-10-22 17:50:18 +03:00
ctxt - > depth - - ;
2022-10-23 14:57:33 +03:00
ref - > expanding = 0 ;
2022-10-21 17:17:48 +03:00
2022-10-23 14:57:33 +03:00
return ( ref ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlXIncludeLoadNode :
* @ ctxt : an XInclude context
2022-10-23 14:57:33 +03:00
* @ ref : an xmlXIncludeRefPtr
2001-02-23 20:55:21 +03:00
*
* Find and load the infoset replacement for the given node .
*
2001-12-31 19:16:02 +03:00
* Returns 0 if substitution succeeded , - 1 if some processing failed
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static int
2022-10-23 14:57:33 +03:00
xmlXIncludeLoadNode ( xmlXIncludeCtxtPtr ctxt , xmlXIncludeRefPtr ref ) {
2001-02-23 20:55:21 +03:00
xmlNodePtr cur ;
2002-08-14 18:11:30 +04:00
int ret ;
2001-02-23 20:55:21 +03:00
2022-10-23 14:57:33 +03:00
if ( ( ctxt = = NULL ) | | ( ref = = NULL ) )
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
2022-10-23 14:57:33 +03:00
cur = ref - > elem ;
2001-02-23 20:55:21 +03:00
if ( cur = = NULL )
return ( - 1 ) ;
2023-12-22 23:38:50 +03:00
if ( ref - > xml ) {
ret = xmlXIncludeLoadDoc ( ctxt , ref ) ;
2001-02-23 20:55:21 +03:00
/* xmlXIncludeGetFragment(ctxt, cur, URI); */
} else {
2023-12-22 23:38:50 +03:00
ret = xmlXIncludeLoadTxt ( ctxt , ref ) ;
2002-08-14 18:11:30 +04:00
}
2004-06-07 12:57:27 +04:00
2002-08-14 18:11:30 +04:00
if ( ret < 0 ) {
xmlNodePtr children ;
/*
2019-09-30 18:04:54 +03:00
* Time to try a fallback if available
2002-08-14 18:11:30 +04:00
*/
children = cur - > children ;
while ( children ! = NULL ) {
if ( ( children - > type = = XML_ELEMENT_NODE ) & &
( children - > ns ! = NULL ) & &
( xmlStrEqual ( children - > name , XINCLUDE_FALLBACK ) ) & &
2003-12-08 20:41:29 +03:00
( ( xmlStrEqual ( children - > ns - > href , XINCLUDE_NS ) ) | |
( xmlStrEqual ( children - > ns - > href , XINCLUDE_OLD_NS ) ) ) ) {
2022-10-23 14:57:33 +03:00
ret = xmlXIncludeLoadFallback ( ctxt , children , ref ) ;
2020-08-17 00:38:48 +03:00
break ;
2002-08-14 18:11:30 +04:00
}
children = children - > next ;
}
}
if ( ret < 0 ) {
2022-10-23 14:57:33 +03:00
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_NO_FALLBACK ,
2003-10-09 02:38:13 +04:00
" could not load %s, and no fallback was found \n " ,
2023-12-22 23:38:50 +03:00
ref - > URI ) ;
2001-02-23 20:55:21 +03:00
}
return ( 0 ) ;
}
/**
* xmlXIncludeIncludeNode :
* @ ctxt : an XInclude context
2022-10-23 14:57:33 +03:00
* @ ref : an xmlXIncludeRefPtr
2001-02-23 20:55:21 +03:00
*
2019-09-30 18:04:54 +03:00
* Implement the infoset replacement for the given node
2001-02-23 20:55:21 +03:00
*
2001-12-31 19:16:02 +03:00
* Returns 0 if substitution succeeded , - 1 if some processing failed
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static int
2022-10-23 14:57:33 +03:00
xmlXIncludeIncludeNode ( xmlXIncludeCtxtPtr ctxt , xmlXIncludeRefPtr ref ) {
2003-02-13 14:02:08 +03:00
xmlNodePtr cur , end , list , tmp ;
2001-02-23 20:55:21 +03:00
2022-10-23 14:57:33 +03:00
if ( ( ctxt = = NULL ) | | ( ref = = NULL ) )
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
2022-10-23 14:57:33 +03:00
cur = ref - > elem ;
2012-08-09 10:24:02 +04:00
if ( ( cur = = NULL ) | | ( cur - > type = = XML_NAMESPACE_DECL ) )
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
2022-10-23 14:57:33 +03:00
list = ref - > inc ;
ref - > inc = NULL ;
2003-02-13 14:02:08 +03:00
/*
* Check against the risk of generating a multi - rooted document
*/
if ( ( cur - > parent ! = NULL ) & &
( cur - > parent - > type ! = XML_ELEMENT_NODE ) ) {
int nb_elem = 0 ;
tmp = list ;
while ( tmp ! = NULL ) {
if ( tmp - > type = = XML_ELEMENT_NODE )
nb_elem + + ;
tmp = tmp - > next ;
}
2024-06-17 22:06:46 +03:00
if ( nb_elem ! = 1 ) {
if ( nb_elem > 1 )
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_MULTIPLE_ROOT ,
" XInclude error: would result in multiple root "
" nodes \n " , NULL ) ;
else
xmlXIncludeErr ( ctxt , ref - > elem , XML_XINCLUDE_MULTIPLE_ROOT ,
" XInclude error: would result in no root "
" node \n " , NULL ) ;
2020-06-10 16:11:40 +03:00
xmlFreeNodeList ( list ) ;
2003-02-13 14:02:08 +03:00
return ( - 1 ) ;
}
}
2004-08-16 16:34:50 +04:00
if ( ctxt - > parseFlags & XML_PARSE_NOXINCNODE ) {
/*
* Add the list of nodes
2024-03-29 13:16:45 +03:00
*
* TODO : Coalesce text nodes unless we are streaming mode .
2004-08-16 16:34:50 +04:00
*/
while ( list ! = NULL ) {
end = list ;
list = list - > next ;
2001-02-23 20:55:21 +03:00
2024-03-22 14:26:28 +03:00
if ( xmlAddPrevSibling ( cur , end ) = = NULL ) {
xmlUnlinkNode ( end ) ;
xmlFreeNode ( end ) ;
goto err_memory ;
}
2004-08-16 16:34:50 +04:00
}
xmlUnlinkNode ( cur ) ;
xmlFreeNode ( cur ) ;
} else {
2020-08-06 18:51:57 +03:00
xmlNodePtr child , next ;
2004-08-16 16:34:50 +04:00
/*
* Change the current node as an XInclude start one , and add an
* XInclude end one
*/
2022-10-23 14:57:33 +03:00
if ( ref - > fallback )
2020-08-17 01:54:12 +03:00
xmlUnsetProp ( cur , BAD_CAST " href " ) ;
2004-08-16 16:34:50 +04:00
cur - > type = XML_XINCLUDE_START ;
2020-08-19 14:07:28 +03:00
/* Remove fallback children */
for ( child = cur - > children ; child ! = NULL ; child = next ) {
next = child - > next ;
xmlUnlinkNode ( child ) ;
xmlFreeNode ( child ) ;
}
2004-10-26 20:06:51 +04:00
end = xmlNewDocNode ( cur - > doc , cur - > ns , cur - > name , NULL ) ;
2024-03-22 14:26:28 +03:00
if ( end = = NULL )
goto err_memory ;
2004-08-16 16:34:50 +04:00
end - > type = XML_XINCLUDE_END ;
2024-03-22 14:26:28 +03:00
if ( xmlAddNextSibling ( cur , end ) = = NULL ) {
xmlFreeNode ( end ) ;
goto err_memory ;
}
2001-02-23 20:55:21 +03:00
2004-08-16 16:34:50 +04:00
/*
* Add the list of nodes
*/
while ( list ! = NULL ) {
2020-08-19 14:07:28 +03:00
cur = list ;
list = list - > next ;
2020-08-17 01:05:19 +03:00
2024-03-22 14:26:28 +03:00
if ( xmlAddPrevSibling ( end , cur ) = = NULL ) {
xmlUnlinkNode ( cur ) ;
xmlFreeNode ( cur ) ;
goto err_memory ;
}
2020-08-19 14:07:28 +03:00
}
2001-02-23 20:55:21 +03:00
}
2002-02-10 14:57:22 +03:00
2012-09-11 09:26:36 +04:00
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
2024-03-22 14:26:28 +03:00
err_memory :
xmlXIncludeErrMemory ( ctxt ) ;
xmlFreeNodeList ( list ) ;
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlXIncludeTestNode :
2003-02-13 14:02:08 +03:00
* @ ctxt : the XInclude processing context
2001-02-23 20:55:21 +03:00
* @ node : an XInclude node
*
* test if the node is an XInclude node
*
* Returns 1 true , 0 otherwise
*/
2001-03-24 20:00:36 +03:00
static int
2003-02-13 14:02:08 +03:00
xmlXIncludeTestNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
2001-02-23 20:55:21 +03:00
if ( node = = NULL )
return ( 0 ) ;
2003-07-06 21:35:43 +04:00
if ( node - > type ! = XML_ELEMENT_NODE )
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
if ( node - > ns = = NULL )
return ( 0 ) ;
2003-12-08 20:41:29 +03:00
if ( ( xmlStrEqual ( node - > ns - > href , XINCLUDE_NS ) ) | |
( xmlStrEqual ( node - > ns - > href , XINCLUDE_OLD_NS ) ) ) {
if ( xmlStrEqual ( node - > ns - > href , XINCLUDE_OLD_NS ) ) {
if ( ctxt - > legacy = = 0 ) {
2003-12-09 14:35:37 +03:00
ctxt - > legacy = 1 ;
2003-12-08 20:41:29 +03:00
}
}
2003-02-13 14:02:08 +03:00
if ( xmlStrEqual ( node - > name , XINCLUDE_NODE ) ) {
xmlNodePtr child = node - > children ;
int nb_fallback = 0 ;
while ( child ! = NULL ) {
if ( ( child - > type = = XML_ELEMENT_NODE ) & &
( child - > ns ! = NULL ) & &
2003-12-08 20:41:29 +03:00
( ( xmlStrEqual ( child - > ns - > href , XINCLUDE_NS ) ) | |
( xmlStrEqual ( child - > ns - > href , XINCLUDE_OLD_NS ) ) ) ) {
2003-02-13 14:02:08 +03:00
if ( xmlStrEqual ( child - > name , XINCLUDE_NODE ) ) {
2003-10-09 02:38:13 +04:00
xmlXIncludeErr ( ctxt , node ,
XML_XINCLUDE_INCLUDE_IN_INCLUDE ,
" %s has an 'include' child \n " ,
XINCLUDE_NODE ) ;
2003-02-13 14:02:08 +03:00
return ( 0 ) ;
}
if ( xmlStrEqual ( child - > name , XINCLUDE_FALLBACK ) ) {
nb_fallback + + ;
}
}
child = child - > next ;
}
if ( nb_fallback > 1 ) {
2003-10-09 02:38:13 +04:00
xmlXIncludeErr ( ctxt , node , XML_XINCLUDE_FALLBACKS_IN_INCLUDE ,
" %s has multiple fallback children \n " ,
XINCLUDE_NODE ) ;
2003-02-13 14:02:08 +03:00
return ( 0 ) ;
}
return ( 1 ) ;
}
if ( xmlStrEqual ( node - > name , XINCLUDE_FALLBACK ) ) {
if ( ( node - > parent = = NULL ) | |
( node - > parent - > type ! = XML_ELEMENT_NODE ) | |
( node - > parent - > ns = = NULL ) | |
2003-12-08 20:41:29 +03:00
( ( ! xmlStrEqual ( node - > parent - > ns - > href , XINCLUDE_NS ) ) & &
( ! xmlStrEqual ( node - > parent - > ns - > href , XINCLUDE_OLD_NS ) ) ) | |
2003-02-13 14:02:08 +03:00
( ! xmlStrEqual ( node - > parent - > name , XINCLUDE_NODE ) ) ) {
2003-10-09 02:38:13 +04:00
xmlXIncludeErr ( ctxt , node ,
XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE ,
" %s is not the child of an 'include' \n " ,
XINCLUDE_FALLBACK ) ;
2003-02-13 14:02:08 +03:00
}
}
}
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/**
2001-05-23 17:44:21 +04:00
* xmlXIncludeDoProcess :
2003-02-13 14:02:08 +03:00
* @ ctxt : the XInclude processing context
2003-07-23 00:52:14 +04:00
* @ tree : the top of the tree to process
2001-02-23 20:55:21 +03:00
*
* Implement the XInclude substitution on the XML document @ doc
*
2001-12-31 19:16:02 +03:00
* Returns 0 if no substitution were done , - 1 if some processing failed
2001-02-23 20:55:21 +03:00
* or the number of substitutions done .
*/
2001-05-23 17:44:21 +04:00
static int
2022-10-23 18:52:29 +03:00
xmlXIncludeDoProcess ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr tree ) {
xmlXIncludeRefPtr ref ;
2001-02-23 20:55:21 +03:00
xmlNodePtr cur ;
int ret = 0 ;
2022-10-30 14:03:51 +03:00
int i , start ;
2001-02-23 20:55:21 +03:00
/*
* First phase : lookup the elements in the document
*/
2022-10-30 14:03:51 +03:00
start = ctxt - > incNr ;
2022-10-23 18:52:29 +03:00
cur = tree ;
2020-08-07 19:39:19 +03:00
do {
2001-02-23 20:55:21 +03:00
/* TODO: need to work on entities -> stack */
2020-06-10 17:34:52 +03:00
if ( xmlXIncludeTestNode ( ctxt , cur ) = = 1 ) {
2022-10-23 18:52:29 +03:00
ref = xmlXIncludeExpandNode ( ctxt , cur ) ;
/*
* Mark direct includes .
*/
if ( ref ! = NULL )
ref - > replace = 1 ;
2020-06-10 17:34:52 +03:00
} else if ( ( cur - > children ! = NULL ) & &
2021-04-22 20:26:28 +03:00
( ( cur - > type = = XML_DOCUMENT_NODE ) | |
( cur - > type = = XML_ELEMENT_NODE ) ) ) {
2020-06-10 17:34:52 +03:00
cur = cur - > children ;
continue ;
}
2020-08-07 19:39:19 +03:00
do {
if ( cur = = tree )
break ;
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
break ;
}
cur = cur - > parent ;
} while ( cur ! = NULL ) ;
} while ( ( cur ! = NULL ) & & ( cur ! = tree ) ) ;
2001-02-23 20:55:21 +03:00
/*
2022-10-21 17:17:48 +03:00
* Second phase : extend the original document infoset .
2001-02-23 20:55:21 +03:00
*/
2022-10-30 14:03:51 +03:00
for ( i = start ; i < ctxt - > incNr ; i + + ) {
2022-10-23 18:52:29 +03:00
if ( ctxt - > incTab [ i ] - > replace ! = 0 ) {
2023-12-26 02:42:22 +03:00
xmlXIncludeIncludeNode ( ctxt , ctxt - > incTab [ i ] ) ;
2022-10-30 14:03:51 +03:00
ctxt - > incTab [ i ] - > replace = 0 ;
2022-10-23 18:52:29 +03:00
} else {
/*
* Ignore includes which were added indirectly , for example
* inside xi : fallback elements .
*/
if ( ctxt - > incTab [ i ] - > inc ! = NULL ) {
xmlFreeNodeList ( ctxt - > incTab [ i ] - > inc ) ;
ctxt - > incTab [ i ] - > inc = NULL ;
}
}
2022-10-21 17:17:48 +03:00
ret + + ;
2001-02-23 20:55:21 +03:00
}
2022-10-30 14:21:20 +03:00
if ( ctxt - > isStream ) {
/*
* incTab references nodes which will eventually be deleted in
* streaming mode . The table is only required for XPointer
* expressions which aren ' t allowed in streaming mode .
*/
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
xmlXIncludeFreeRef ( ctxt - > incTab [ i ] ) ;
}
ctxt - > incNr = 0 ;
}
2001-05-23 17:44:21 +04:00
return ( ret ) ;
}
2023-12-10 20:15:59 +03:00
/**
* xmlXIncludeDoProcessRoot :
* @ ctxt : the XInclude processing context
* @ tree : the top of the tree to process
*
* Implement the XInclude substitution on the XML document @ doc
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
static int
xmlXIncludeDoProcessRoot ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr tree ) {
if ( ( tree = = NULL ) | | ( tree - > type = = XML_NAMESPACE_DECL ) )
return ( - 1 ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
2023-12-22 23:38:50 +03:00
return ( xmlXIncludeDoProcess ( ctxt , tree ) ) ;
2023-12-10 20:15:59 +03:00
}
/**
* xmlXIncludeGetLastError :
* @ ctxt : an XInclude processing context
*
2024-05-20 14:58:22 +03:00
* Available since 2.13 .0 .
*
2023-12-10 20:15:59 +03:00
* Returns the last error code .
*/
int
xmlXIncludeGetLastError ( xmlXIncludeCtxtPtr ctxt ) {
if ( ctxt = = NULL )
2024-01-02 19:45:54 +03:00
return ( XML_ERR_ARGUMENT ) ;
2023-12-10 20:15:59 +03:00
return ( ctxt - > errNo ) ;
}
2023-12-18 21:43:55 +03:00
/**
* xmlXIncludeSetErrorHandler :
* @ ctxt : an XInclude processing context
* @ handler : error handler
* @ data : user data which will be passed to the handler
*
2023-12-21 19:30:38 +03:00
* Register a callback function that will be called on errors and
* warnings . If handler is NULL , the error handler will be deactivated .
*
* Available since 2.13 .0 .
2023-12-18 21:43:55 +03:00
*/
void
xmlXIncludeSetErrorHandler ( xmlXIncludeCtxtPtr ctxt ,
xmlStructuredErrorFunc handler , void * data ) {
if ( ctxt = = NULL )
return ;
ctxt - > errorHandler = handler ;
ctxt - > errorCtxt = data ;
}
2024-06-11 15:40:28 +03:00
/**
* xmlXIncludeSetResourceLoader :
* @ ctxt : an XInclude processing context
* @ loader : resource loader
* @ data : user data which will be passed to the loader
*
* Register a callback function that will be called to load included
* documents .
*
* Available since 2.14 .0 .
*/
void
xmlXIncludeSetResourceLoader ( xmlXIncludeCtxtPtr ctxt ,
xmlResourceLoader loader , void * data ) {
if ( ctxt = = NULL )
return ;
ctxt - > resourceLoader = loader ;
ctxt - > resourceCtxt = data ;
}
2001-05-23 17:44:21 +04:00
/**
2003-12-09 14:35:37 +03:00
* xmlXIncludeSetFlags :
* @ ctxt : an XInclude processing context
* @ flags : a set of xmlParserOption used for parsing XML includes
*
* Set the flags used for further processing of XML resources .
*
* Returns 0 in case of success and - 1 in case of error .
*/
int
xmlXIncludeSetFlags ( xmlXIncludeCtxtPtr ctxt , int flags ) {
if ( ctxt = = NULL )
return ( - 1 ) ;
ctxt - > parseFlags = flags ;
return ( 0 ) ;
}
2009-08-24 21:45:54 +04:00
2022-10-30 14:21:20 +03:00
/**
* xmlXIncludeSetStreamingMode :
* @ ctxt : an XInclude processing context
* @ mode : whether streaming mode should be enabled
*
* In streaming mode , XPointer expressions aren ' t allowed .
*
* Returns 0 in case of success and - 1 in case of error .
*/
int
xmlXIncludeSetStreamingMode ( xmlXIncludeCtxtPtr ctxt , int mode ) {
if ( ctxt = = NULL )
return ( - 1 ) ;
ctxt - > isStream = ! ! mode ;
return ( 0 ) ;
}
2009-08-24 21:45:54 +04:00
/**
* xmlXIncludeProcessTreeFlagsData :
* @ tree : an XML node
* @ flags : a set of xmlParserOption used for parsing XML includes
* @ data : application data that will be passed to the parser context
* in the _private field of the parser context ( s )
*
* Implement the XInclude substitution on the XML node @ tree
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
xmlXIncludeProcessTreeFlagsData ( xmlNodePtr tree , int flags , void * data ) {
xmlXIncludeCtxtPtr ctxt ;
int ret = 0 ;
2012-08-09 10:24:02 +04:00
if ( ( tree = = NULL ) | | ( tree - > type = = XML_NAMESPACE_DECL ) | |
( tree - > doc = = NULL ) )
2009-08-24 21:45:54 +04:00
return ( - 1 ) ;
ctxt = xmlXIncludeNewContext ( tree - > doc ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
ctxt - > _private = data ;
xmlXIncludeSetFlags ( ctxt , flags ) ;
2023-12-10 20:15:59 +03:00
ret = xmlXIncludeDoProcessRoot ( ctxt , tree ) ;
2009-08-24 21:45:54 +04:00
if ( ( ret > = 0 ) & & ( ctxt - > nbErrors > 0 ) )
ret = - 1 ;
xmlXIncludeFreeContext ( ctxt ) ;
return ( ret ) ;
}
2003-12-09 14:35:37 +03:00
/**
2006-09-29 13:16:00 +04:00
* xmlXIncludeProcessFlagsData :
2001-05-23 17:44:21 +04:00
* @ doc : an XML document
2003-12-09 14:35:37 +03:00
* @ flags : a set of xmlParserOption used for parsing XML includes
2006-09-29 13:16:00 +04:00
* @ data : application data that will be passed to the parser context
* in the _private field of the parser context ( s )
2001-05-23 17:44:21 +04:00
*
* Implement the XInclude substitution on the XML document @ doc
*
2001-12-31 19:16:02 +03:00
* Returns 0 if no substitution were done , - 1 if some processing failed
2001-05-23 17:44:21 +04:00
* or the number of substitutions done .
*/
int
2006-09-29 13:16:00 +04:00
xmlXIncludeProcessFlagsData ( xmlDocPtr doc , int flags , void * data ) {
2003-07-23 00:52:14 +04:00
xmlNodePtr tree ;
2001-05-23 17:44:21 +04:00
if ( doc = = NULL )
return ( - 1 ) ;
2003-07-23 00:52:14 +04:00
tree = xmlDocGetRootElement ( doc ) ;
if ( tree = = NULL )
return ( - 1 ) ;
2009-08-24 21:45:54 +04:00
return ( xmlXIncludeProcessTreeFlagsData ( tree , flags , data ) ) ;
2003-07-23 00:52:14 +04:00
}
2006-09-29 13:16:00 +04:00
/**
* xmlXIncludeProcessFlags :
* @ doc : an XML document
* @ flags : a set of xmlParserOption used for parsing XML includes
*
* Implement the XInclude substitution on the XML document @ doc
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
xmlXIncludeProcessFlags ( xmlDocPtr doc , int flags ) {
return xmlXIncludeProcessFlagsData ( doc , flags , NULL ) ;
}
2003-07-23 00:52:14 +04:00
/**
2003-12-09 14:35:37 +03:00
* xmlXIncludeProcess :
* @ doc : an XML document
*
* Implement the XInclude substitution on the XML document @ doc
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
xmlXIncludeProcess ( xmlDocPtr doc ) {
return ( xmlXIncludeProcessFlags ( doc , 0 ) ) ;
}
/**
* xmlXIncludeProcessTreeFlags :
2003-07-23 00:52:14 +04:00
* @ tree : a node in an XML document
2003-12-09 14:35:37 +03:00
* @ flags : a set of xmlParserOption used for parsing XML includes
2003-07-23 00:52:14 +04:00
*
* Implement the XInclude substitution for the given subtree
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
2003-12-09 14:35:37 +03:00
xmlXIncludeProcessTreeFlags ( xmlNodePtr tree , int flags ) {
2003-07-23 00:52:14 +04:00
xmlXIncludeCtxtPtr ctxt ;
int ret = 0 ;
2012-08-09 10:24:02 +04:00
if ( ( tree = = NULL ) | | ( tree - > type = = XML_NAMESPACE_DECL ) | |
( tree - > doc = = NULL ) )
2003-07-23 00:52:14 +04:00
return ( - 1 ) ;
ctxt = xmlXIncludeNewContext ( tree - > doc ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
2003-12-09 14:35:37 +03:00
xmlXIncludeSetFlags ( ctxt , flags ) ;
2023-12-10 20:15:59 +03:00
ret = xmlXIncludeDoProcessRoot ( ctxt , tree ) ;
2003-02-11 21:03:05 +03:00
if ( ( ret > = 0 ) & & ( ctxt - > nbErrors > 0 ) )
ret = - 1 ;
2001-05-23 17:44:21 +04:00
2001-02-23 20:55:21 +03:00
xmlXIncludeFreeContext ( ctxt ) ;
return ( ret ) ;
}
2003-12-09 14:35:37 +03:00
/**
* xmlXIncludeProcessTree :
* @ tree : a node in an XML document
*
* Implement the XInclude substitution for the given subtree
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
xmlXIncludeProcessTree ( xmlNodePtr tree ) {
return ( xmlXIncludeProcessTreeFlags ( tree , 0 ) ) ;
}
2003-11-03 15:31:38 +03:00
/**
* xmlXIncludeProcessNode :
* @ ctxt : an existing XInclude context
* @ node : a node in an XML document
*
* Implement the XInclude substitution for the given subtree reusing
2020-03-08 19:19:42 +03:00
* the information and data coming from the given context .
2003-11-03 15:31:38 +03:00
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
xmlXIncludeProcessNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
int ret = 0 ;
2012-08-09 10:24:02 +04:00
if ( ( node = = NULL ) | | ( node - > type = = XML_NAMESPACE_DECL ) | |
( node - > doc = = NULL ) | | ( ctxt = = NULL ) )
2003-11-03 15:31:38 +03:00
return ( - 1 ) ;
2023-12-10 20:15:59 +03:00
ret = xmlXIncludeDoProcessRoot ( ctxt , node ) ;
2003-11-03 15:31:38 +03:00
if ( ( ret > = 0 ) & & ( ctxt - > nbErrors > 0 ) )
ret = - 1 ;
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
# else /* !LIBXML_XINCLUDE_ENABLED */
# endif