2002-03-04 20:09:44 +03:00
/*
2012-09-11 09:26:36 +04:00
* " Canonical XML " implementation
2002-03-04 20:09:44 +03:00
* http : //www.w3.org/TR/xml-c14n
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* " Exclusive XML Canonicalization " implementation
* http : //www.w3.org/TR/xml-exc-c14n
*
* See Copyright for the status of this software .
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Author : Aleksey Sanin < aleksey @ aleksey . com >
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2002-03-04 20:09:44 +03:00
# include "libxml.h"
# ifdef LIBXML_C14N_ENABLED
# include <stdlib.h>
# include <string.h>
# include <libxml/tree.h>
# include <libxml/parser.h>
2002-03-11 12:15:32 +03:00
# include <libxml/uri.h>
2002-03-04 20:09:44 +03:00
# include <libxml/xmlerror.h>
# include <libxml/xpathInternals.h>
# include <libxml/c14n.h>
2022-08-26 02:22:33 +03:00
# include "private/error.h"
2024-02-16 17:42:38 +03:00
# include "private/io.h"
2012-07-16 10:37:00 +04:00
2002-03-04 20:09:44 +03:00
/************************************************************************
* *
* Some declaration better left private ATM *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-11 12:15:32 +03:00
typedef enum {
XMLC14N_BEFORE_DOCUMENT_ELEMENT = 0 ,
XMLC14N_INSIDE_DOCUMENT_ELEMENT = 1 ,
XMLC14N_AFTER_DOCUMENT_ELEMENT = 2
2002-03-04 20:09:44 +03:00
} xmlC14NPosition ;
2002-06-04 08:27:06 +04:00
typedef struct _xmlC14NVisibleNsStack {
2005-03-20 22:16:47 +03:00
int nsCurEnd ; /* number of nodes in the set */
2019-09-30 18:04:54 +03:00
int nsPrevStart ; /* the beginning of the stack for previous visible node */
2005-03-20 22:16:47 +03:00
int nsPrevEnd ; /* the end of the stack for previous visible node */
int nsMax ; /* size of the array as allocated */
2012-09-11 09:26:36 +04:00
xmlNsPtr * nsTab ; /* array of ns in no particular order */
2005-03-20 22:16:47 +03:00
xmlNodePtr * nodeTab ; /* array of nodes in no particular order */
2002-06-04 08:27:06 +04:00
} xmlC14NVisibleNsStack , * xmlC14NVisibleNsStackPtr ;
2002-05-31 08:24:13 +04:00
2002-03-04 20:09:44 +03:00
typedef struct _xmlC14NCtx {
/* input parameters */
2002-03-11 12:15:32 +03:00
xmlDocPtr doc ;
2002-08-01 10:31:50 +04:00
xmlC14NIsVisibleCallback is_visible_callback ;
2012-09-11 09:26:36 +04:00
void * user_data ;
2002-03-11 12:15:32 +03:00
int with_comments ;
xmlOutputBufferPtr buf ;
2002-03-04 20:09:44 +03:00
/* position in the XML document */
2002-03-11 12:15:32 +03:00
xmlC14NPosition pos ;
int parent_is_doc ;
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStackPtr ns_rendered ;
2012-09-11 09:26:36 +04:00
2009-07-09 12:26:22 +04:00
/* C14N mode */
xmlC14NMode mode ;
2002-03-04 20:09:44 +03:00
/* exclusive canonicalization */
2002-03-11 12:15:32 +03:00
xmlChar * * inclusive_ns_prefixes ;
2003-10-10 16:30:37 +04:00
/* error number */
int error ;
2002-03-04 20:09:44 +03:00
} xmlC14NCtx , * xmlC14NCtxPtr ;
2002-08-01 10:31:50 +04:00
static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate ( void ) ;
2005-03-20 22:16:47 +03:00
static void xmlC14NVisibleNsStackDestroy ( xmlC14NVisibleNsStackPtr cur ) ;
2024-02-04 16:08:44 +03:00
static int xmlC14NVisibleNsStackAdd ( xmlC14NVisibleNsStackPtr cur ,
2005-03-20 22:16:47 +03:00
xmlNsPtr ns ,
xmlNodePtr node ) ;
2012-09-11 09:26:36 +04:00
static void xmlC14NVisibleNsStackSave ( xmlC14NVisibleNsStackPtr cur ,
2002-08-01 10:31:50 +04:00
xmlC14NVisibleNsStackPtr state ) ;
2012-09-11 09:26:36 +04:00
static void xmlC14NVisibleNsStackRestore ( xmlC14NVisibleNsStackPtr cur ,
2002-08-01 10:31:50 +04:00
xmlC14NVisibleNsStackPtr state ) ;
2012-09-11 09:26:36 +04:00
static void xmlC14NVisibleNsStackShift ( xmlC14NVisibleNsStackPtr cur ) ;
static int xmlC14NVisibleNsStackFind ( xmlC14NVisibleNsStackPtr cur ,
2002-08-01 10:31:50 +04:00
xmlNsPtr ns ) ;
2012-09-11 09:26:36 +04:00
static int xmlExcC14NVisibleNsStackFind ( xmlC14NVisibleNsStackPtr cur ,
2002-08-01 10:31:50 +04:00
xmlNsPtr ns ,
xmlC14NCtxPtr ctx ) ;
2017-11-09 19:29:22 +03:00
static int xmlC14NIsNodeInNodeset ( void * user_data ,
2002-08-01 10:31:50 +04:00
xmlNodePtr node ,
xmlNodePtr parent ) ;
2002-03-04 20:09:44 +03:00
2002-03-11 12:15:32 +03:00
static int xmlC14NProcessNode ( xmlC14NCtxPtr ctx , xmlNodePtr cur ) ;
static int xmlC14NProcessNodeList ( xmlC14NCtxPtr ctx , xmlNodePtr cur ) ;
2002-03-04 20:09:44 +03:00
typedef enum {
2002-03-11 12:15:32 +03:00
XMLC14N_NORMALIZE_ATTR = 0 ,
XMLC14N_NORMALIZE_COMMENT = 1 ,
XMLC14N_NORMALIZE_PI = 2 ,
XMLC14N_NORMALIZE_TEXT = 3
} xmlC14NNormalizationMode ;
2002-03-04 20:09:44 +03:00
2002-03-11 12:15:32 +03:00
static xmlChar * xmlC11NNormalizeString ( const xmlChar * input ,
xmlC14NNormalizationMode mode ) ;
2002-03-04 20:09:44 +03:00
2012-09-11 09:26:36 +04:00
# define xmlC11NNormalizeAttr( a ) \
2002-03-11 12:15:32 +03:00
xmlC11NNormalizeString ( ( a ) , XMLC14N_NORMALIZE_ATTR )
2012-09-11 09:26:36 +04:00
# define xmlC11NNormalizeComment( a ) \
2002-03-11 12:15:32 +03:00
xmlC11NNormalizeString ( ( a ) , XMLC14N_NORMALIZE_COMMENT )
2012-09-11 09:26:36 +04:00
# define xmlC11NNormalizePI( a ) \
2002-03-11 12:15:32 +03:00
xmlC11NNormalizeString ( ( a ) , XMLC14N_NORMALIZE_PI )
2012-09-11 09:26:36 +04:00
# define xmlC11NNormalizeText( a ) \
2002-03-11 12:15:32 +03:00
xmlC11NNormalizeString ( ( a ) , XMLC14N_NORMALIZE_TEXT )
2002-03-04 20:09:44 +03:00
2012-09-11 09:26:36 +04:00
# define xmlC14NIsVisible( ctx, node, parent ) \
2002-08-01 10:31:50 +04:00
( ( ( ctx ) - > is_visible_callback ! = NULL ) ? \
( ctx ) - > is_visible_callback ( ( ctx ) - > user_data , \
( xmlNodePtr ) ( node ) , ( xmlNodePtr ) ( parent ) ) : 1 )
2003-10-10 16:30:37 +04:00
2012-09-11 09:26:36 +04:00
# define xmlC14NIsExclusive( ctx ) \
2009-07-09 12:26:22 +04:00
( ( ctx ) - > mode = = XML_C14N_EXCLUSIVE_1_0 )
2003-10-10 16:30:37 +04:00
/************************************************************************
* *
2012-09-11 09:26:36 +04:00
* Some factorized error routines *
2003-10-10 16:30:37 +04:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlC14NErrMemory :
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2003-10-10 16:30:37 +04:00
*
2005-03-20 22:16:47 +03:00
* Handle a redefinition of memory error
2003-10-10 16:30:37 +04:00
*/
static void
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( xmlC14NCtxPtr ctxt )
2003-10-10 16:30:37 +04:00
{
2024-02-04 16:08:44 +03:00
if ( ctxt ! = NULL )
ctxt - > error = XML_ERR_NO_MEMORY ;
2023-12-18 22:58:42 +03:00
xmlRaiseMemoryError ( NULL , NULL , NULL , XML_FROM_C14N , NULL ) ;
}
static void
xmlC14NErrFull ( xmlC14NCtxPtr ctxt , xmlNodePtr node , int code , const char * str1 ,
const char * msg , . . . )
{
va_list ap ;
int res ;
if ( ctxt ! = NULL )
ctxt - > error = code ;
va_start ( ap , msg ) ;
res = xmlVRaiseError ( NULL , NULL , NULL , ctxt , node ,
XML_FROM_C14N , code , XML_ERR_ERROR , NULL , 0 ,
str1 , NULL , NULL , 0 , 0 ,
msg , ap ) ;
va_end ( ap ) ;
if ( res < 0 )
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctxt ) ;
2003-10-10 16:30:37 +04:00
}
2005-03-20 22:16:47 +03:00
/**
* xmlC14NErrParam :
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2005-03-20 22:16:47 +03:00
*
2023-12-18 22:58:42 +03:00
* Handle a param error
2005-03-20 22:16:47 +03:00
*/
static void
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( xmlC14NCtxPtr ctxt )
2005-03-20 22:16:47 +03:00
{
2023-12-18 22:58:42 +03:00
xmlC14NErrFull ( ctxt , NULL , XML_ERR_ARGUMENT , NULL ,
" Invalid argument \n " , NULL ) ;
2005-03-20 22:16:47 +03:00
}
/**
* xmlC14NErrInvalidNode :
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2005-03-20 22:16:47 +03:00
*
2023-12-18 22:58:42 +03:00
* Handle an invalid node error
2005-03-20 22:16:47 +03:00
*/
static void
2023-12-18 22:58:42 +03:00
xmlC14NErrInvalidNode ( xmlC14NCtxPtr ctxt , const char * node_type ,
const char * extra )
2005-03-20 22:16:47 +03:00
{
2023-12-18 22:58:42 +03:00
xmlC14NErrFull ( ctxt , NULL , XML_C14N_INVALID_NODE , extra ,
" Node %s is invalid here : %s \n " , node_type , extra ) ;
2005-03-20 22:16:47 +03:00
}
/**
* xmlC14NErrUnknownNode :
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2005-03-20 22:16:47 +03:00
*
2023-12-18 22:58:42 +03:00
* Handle an unknown node error
2005-03-20 22:16:47 +03:00
*/
static void
2023-12-18 22:58:42 +03:00
xmlC14NErrUnknownNode ( xmlC14NCtxPtr ctxt , int node_type , const char * extra )
2005-03-20 22:16:47 +03:00
{
2023-12-18 22:58:42 +03:00
xmlC14NErrFull ( ctxt , NULL , XML_C14N_UNKNOW_NODE , extra ,
" Unknown node type %d found : %s \n " , node_type , extra ) ;
2005-03-20 22:16:47 +03:00
}
/**
* xmlC14NErrRelativeNamespace :
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2005-03-20 22:16:47 +03:00
*
2023-12-18 22:58:42 +03:00
* Handle a relative namespace error
2005-03-20 22:16:47 +03:00
*/
static void
2023-12-18 22:58:42 +03:00
xmlC14NErrRelativeNamespace ( xmlC14NCtxPtr ctxt , const char * ns_uri )
2005-03-20 22:16:47 +03:00
{
2023-12-18 22:58:42 +03:00
xmlC14NErrFull ( ctxt , NULL , XML_C14N_RELATIVE_NAMESPACE , ns_uri ,
" Relative namespace UR is invalid here : %s \n " , ns_uri ) ;
2005-03-20 22:16:47 +03:00
}
2003-10-10 16:30:37 +04:00
/**
* xmlC14NErr :
* @ ctxt : a C14N evaluation context
* @ node : the context node
2019-09-30 18:04:54 +03:00
* @ error : the error code
2003-10-10 16:30:37 +04:00
* @ msg : the message
2020-03-08 19:19:42 +03:00
* @ extra : extra information
2003-10-10 16:30:37 +04:00
*
2023-12-18 22:58:42 +03:00
* Handle an error
2003-10-10 16:30:37 +04:00
*/
static void
xmlC14NErr ( xmlC14NCtxPtr ctxt , xmlNodePtr node , int error ,
const char * msg )
{
2023-12-18 22:58:42 +03:00
xmlC14NErrFull ( ctxt , node , error , NULL , " %s " , msg ) ;
2003-10-10 16:30:37 +04:00
}
2002-03-04 20:09:44 +03:00
/************************************************************************
* *
* The implementation internals *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-05-31 08:24:13 +04:00
# define XML_NAMESPACES_DEFAULT 16
2012-09-11 09:26:36 +04:00
static int
2017-11-09 19:29:22 +03:00
xmlC14NIsNodeInNodeset ( void * user_data , xmlNodePtr node , xmlNodePtr parent ) {
xmlNodeSetPtr nodes = ( xmlNodeSetPtr ) user_data ;
2002-08-01 10:31:50 +04:00
if ( ( nodes ! = NULL ) & & ( node ! = NULL ) ) {
if ( node - > type ! = XML_NAMESPACE_DECL ) {
return ( xmlXPathNodeSetContains ( nodes , node ) ) ;
} else {
xmlNs ns ;
2012-09-11 09:26:36 +04:00
memcpy ( & ns , node , sizeof ( ns ) ) ;
2004-04-20 06:05:30 +04:00
/* this is a libxml hack! check xpath.c for details */
if ( ( parent ! = NULL ) & & ( parent - > type = = XML_ATTRIBUTE_NODE ) ) {
ns . next = ( xmlNsPtr ) parent - > parent ;
} else {
2012-09-11 09:26:36 +04:00
ns . next = ( xmlNsPtr ) parent ;
2004-04-20 06:05:30 +04:00
}
2002-08-01 10:31:50 +04:00
2012-09-11 09:26:36 +04:00
/*
* If the input is an XPath node - set , then the node - set must explicitly
2002-08-01 10:31:50 +04:00
* contain every node to be rendered to the canonical form .
*/
return ( xmlXPathNodeSetContains ( nodes , ( xmlNodePtr ) & ns ) ) ;
}
}
return ( 1 ) ;
}
2002-06-04 08:27:06 +04:00
static xmlC14NVisibleNsStackPtr
xmlC14NVisibleNsStackCreate ( void ) {
xmlC14NVisibleNsStackPtr ret ;
2002-05-31 08:24:13 +04:00
2002-06-04 08:27:06 +04:00
ret = ( xmlC14NVisibleNsStackPtr ) xmlMalloc ( sizeof ( xmlC14NVisibleNsStack ) ) ;
2024-02-04 16:08:44 +03:00
if ( ret = = NULL )
2002-05-31 08:24:13 +04:00
return ( NULL ) ;
2022-09-01 02:18:30 +03:00
memset ( ret , 0 , sizeof ( xmlC14NVisibleNsStack ) ) ;
2002-05-31 08:24:13 +04:00
return ( ret ) ;
}
static void
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStackDestroy ( xmlC14NVisibleNsStackPtr cur ) {
2002-05-31 08:24:13 +04:00
if ( cur = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2005-03-20 22:16:47 +03:00
return ;
2002-05-31 08:24:13 +04:00
}
if ( cur - > nsTab ! = NULL ) {
memset ( cur - > nsTab , 0 , cur - > nsMax * sizeof ( xmlNsPtr ) ) ;
xmlFree ( cur - > nsTab ) ;
}
2002-08-03 03:50:03 +04:00
if ( cur - > nodeTab ! = NULL ) {
memset ( cur - > nodeTab , 0 , cur - > nsMax * sizeof ( xmlNodePtr ) ) ;
xmlFree ( cur - > nodeTab ) ;
}
2002-06-04 08:27:06 +04:00
memset ( cur , 0 , sizeof ( xmlC14NVisibleNsStack ) ) ;
2002-05-31 08:24:13 +04:00
xmlFree ( cur ) ;
2012-09-11 09:26:36 +04:00
2002-05-31 08:24:13 +04:00
}
2024-02-04 16:08:44 +03:00
static int
2002-08-01 10:31:50 +04:00
xmlC14NVisibleNsStackAdd ( xmlC14NVisibleNsStackPtr cur , xmlNsPtr ns , xmlNodePtr node ) {
2012-09-11 09:26:36 +04:00
if ( ( cur = = NULL ) | |
2002-08-01 10:31:50 +04:00
( ( cur - > nsTab = = NULL ) & & ( cur - > nodeTab ! = NULL ) ) | |
2024-02-04 16:08:44 +03:00
( ( cur - > nsTab ! = NULL ) & & ( cur - > nodeTab = = NULL ) ) )
return ( 1 ) ;
2002-05-31 08:24:13 +04:00
2002-08-01 10:31:50 +04:00
if ( ( cur - > nsTab = = NULL ) & & ( cur - > nodeTab = = NULL ) ) {
2002-05-31 08:24:13 +04:00
cur - > nsTab = ( xmlNsPtr * ) xmlMalloc ( XML_NAMESPACES_DEFAULT * sizeof ( xmlNsPtr ) ) ;
2002-08-01 10:31:50 +04:00
cur - > nodeTab = ( xmlNodePtr * ) xmlMalloc ( XML_NAMESPACES_DEFAULT * sizeof ( xmlNodePtr ) ) ;
2024-02-04 16:08:44 +03:00
if ( ( cur - > nsTab = = NULL ) | | ( cur - > nodeTab = = NULL ) )
return ( - 1 ) ;
2002-05-31 08:24:13 +04:00
memset ( cur - > nsTab , 0 , XML_NAMESPACES_DEFAULT * sizeof ( xmlNsPtr ) ) ;
2002-08-01 10:31:50 +04:00
memset ( cur - > nodeTab , 0 , XML_NAMESPACES_DEFAULT * sizeof ( xmlNodePtr ) ) ;
2002-05-31 08:24:13 +04:00
cur - > nsMax = XML_NAMESPACES_DEFAULT ;
2002-06-04 08:27:06 +04:00
} else if ( cur - > nsMax = = cur - > nsCurEnd ) {
2012-09-11 09:26:36 +04:00
void * tmp ;
2002-05-31 08:24:13 +04:00
int tmpSize ;
2012-09-11 09:26:36 +04:00
2002-05-31 08:24:13 +04:00
tmpSize = 2 * cur - > nsMax ;
2002-08-01 10:31:50 +04:00
tmp = xmlRealloc ( cur - > nsTab , tmpSize * sizeof ( xmlNsPtr ) ) ;
2024-02-04 16:08:44 +03:00
if ( tmp = = NULL )
return ( - 1 ) ;
2002-08-01 10:31:50 +04:00
cur - > nsTab = ( xmlNsPtr * ) tmp ;
tmp = xmlRealloc ( cur - > nodeTab , tmpSize * sizeof ( xmlNodePtr ) ) ;
2024-02-04 16:08:44 +03:00
if ( tmp = = NULL )
return ( - 1 ) ;
2002-08-01 10:31:50 +04:00
cur - > nodeTab = ( xmlNodePtr * ) tmp ;
2002-05-31 08:24:13 +04:00
cur - > nsMax = tmpSize ;
}
2002-08-01 10:31:50 +04:00
cur - > nsTab [ cur - > nsCurEnd ] = ns ;
cur - > nodeTab [ cur - > nsCurEnd ] = node ;
+ + cur - > nsCurEnd ;
2024-02-04 16:08:44 +03:00
return ( 0 ) ;
2002-06-04 08:27:06 +04:00
}
static void
xmlC14NVisibleNsStackSave ( xmlC14NVisibleNsStackPtr cur , xmlC14NVisibleNsStackPtr state ) {
if ( ( cur = = NULL ) | | ( state = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-06-04 08:27:06 +04:00
return ;
}
2012-09-11 09:26:36 +04:00
2002-06-04 08:27:06 +04:00
state - > nsCurEnd = cur - > nsCurEnd ;
state - > nsPrevStart = cur - > nsPrevStart ;
state - > nsPrevEnd = cur - > nsPrevEnd ;
}
static void
xmlC14NVisibleNsStackRestore ( xmlC14NVisibleNsStackPtr cur , xmlC14NVisibleNsStackPtr state ) {
if ( ( cur = = NULL ) | | ( state = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-06-04 08:27:06 +04:00
return ;
}
cur - > nsCurEnd = state - > nsCurEnd ;
cur - > nsPrevStart = state - > nsPrevStart ;
cur - > nsPrevEnd = state - > nsPrevEnd ;
}
2012-09-11 09:26:36 +04:00
static void
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStackShift ( xmlC14NVisibleNsStackPtr cur ) {
if ( cur = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-06-04 08:27:06 +04:00
return ;
}
cur - > nsPrevStart = cur - > nsPrevEnd ;
cur - > nsPrevEnd = cur - > nsCurEnd ;
}
static int
xmlC14NStrEqual ( const xmlChar * str1 , const xmlChar * str2 ) {
if ( str1 = = str2 ) return ( 1 ) ;
if ( str1 = = NULL ) return ( ( * str2 ) = = ' \0 ' ) ;
if ( str2 = = NULL ) return ( ( * str1 ) = = ' \0 ' ) ;
do {
if ( * str1 + + ! = * str2 ) return ( 0 ) ;
} while ( * str2 + + ) ;
return ( 1 ) ;
}
/**
* xmlC14NVisibleNsStackFind :
2012-09-11 09:26:36 +04:00
* @ ctx : the C14N context
2002-12-10 18:19:08 +03:00
* @ ns : the namespace to check
2002-06-04 08:27:06 +04:00
*
* Checks whether the given namespace was already rendered or not
*
* Returns 1 if we already wrote this namespace or 0 otherwise
*/
static int
2002-08-01 10:31:50 +04:00
xmlC14NVisibleNsStackFind ( xmlC14NVisibleNsStackPtr cur , xmlNsPtr ns )
2002-06-04 08:27:06 +04:00
{
int i ;
const xmlChar * prefix ;
const xmlChar * href ;
2002-08-01 10:31:50 +04:00
int has_empty_ns ;
2012-09-11 09:26:36 +04:00
2002-06-04 08:27:06 +04:00
if ( cur = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-06-04 08:27:06 +04:00
return ( 0 ) ;
}
/*
2012-09-11 09:26:36 +04:00
* if the default namespace xmlns = " " is not defined yet then
2002-06-04 08:27:06 +04:00
* we do not want to print it out
*/
prefix = ( ( ns = = NULL ) | | ( ns - > prefix = = NULL ) ) ? BAD_CAST " " : ns - > prefix ;
href = ( ( ns = = NULL ) | | ( ns - > href = = NULL ) ) ? BAD_CAST " " : ns - > href ;
2002-08-01 10:31:50 +04:00
has_empty_ns = ( xmlC14NStrEqual ( prefix , NULL ) & & xmlC14NStrEqual ( href , NULL ) ) ;
2002-06-04 08:27:06 +04:00
if ( cur - > nsTab ! = NULL ) {
2002-08-01 10:31:50 +04:00
int start = ( has_empty_ns ) ? 0 : cur - > nsPrevStart ;
2002-06-04 08:27:06 +04:00
for ( i = cur - > nsCurEnd - 1 ; i > = start ; - - i ) {
xmlNsPtr ns1 = cur - > nsTab [ i ] ;
2012-09-11 09:26:36 +04:00
2002-06-04 08:27:06 +04:00
if ( xmlC14NStrEqual ( prefix , ( ns1 ! = NULL ) ? ns1 - > prefix : NULL ) ) {
return ( xmlC14NStrEqual ( href , ( ns1 ! = NULL ) ? ns1 - > href : NULL ) ) ;
}
}
}
2002-08-01 10:31:50 +04:00
return ( has_empty_ns ) ;
2002-05-31 08:24:13 +04:00
}
2012-09-11 09:26:36 +04:00
static int
2002-08-01 10:31:50 +04:00
xmlExcC14NVisibleNsStackFind ( xmlC14NVisibleNsStackPtr cur , xmlNsPtr ns , xmlC14NCtxPtr ctx ) {
int i ;
const xmlChar * prefix ;
const xmlChar * href ;
int has_empty_ns ;
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
if ( cur = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( 0 ) ;
}
2002-03-04 20:09:44 +03:00
2002-08-01 10:31:50 +04:00
/*
2012-09-11 09:26:36 +04:00
* if the default namespace xmlns = " " is not defined yet then
2002-08-01 10:31:50 +04:00
* we do not want to print it out
2002-06-04 08:27:06 +04:00
*/
2002-08-01 10:31:50 +04:00
prefix = ( ( ns = = NULL ) | | ( ns - > prefix = = NULL ) ) ? BAD_CAST " " : ns - > prefix ;
href = ( ( ns = = NULL ) | | ( ns - > href = = NULL ) ) ? BAD_CAST " " : ns - > href ;
has_empty_ns = ( xmlC14NStrEqual ( prefix , NULL ) & & xmlC14NStrEqual ( href , NULL ) ) ;
2002-06-04 08:27:06 +04:00
2002-08-01 10:31:50 +04:00
if ( cur - > nsTab ! = NULL ) {
int start = 0 ;
for ( i = cur - > nsCurEnd - 1 ; i > = start ; - - i ) {
xmlNsPtr ns1 = cur - > nsTab [ i ] ;
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
if ( xmlC14NStrEqual ( prefix , ( ns1 ! = NULL ) ? ns1 - > prefix : NULL ) ) {
if ( xmlC14NStrEqual ( href , ( ns1 ! = NULL ) ? ns1 - > href : NULL ) ) {
2012-09-11 09:26:36 +04:00
return ( xmlC14NIsVisible ( ctx , ns1 , cur - > nodeTab [ i ] ) ) ;
2002-08-01 10:31:50 +04:00
} else {
return ( 0 ) ;
}
}
}
}
return ( has_empty_ns ) ;
2002-06-04 08:27:06 +04:00
}
2002-08-01 10:31:50 +04:00
2002-03-04 20:09:44 +03:00
/**
* xmlC14NIsXmlNs :
2012-09-11 09:26:36 +04:00
* @ ns : the namespace to check
*
2002-03-04 20:09:44 +03:00
* Checks whether the given namespace is a default " xml: " namespace
* with href = " http://www.w3.org/XML/1998/namespace "
*
* Returns 1 if the node is default or 0 otherwise
*/
2002-03-11 12:15:32 +03:00
2002-03-04 20:09:44 +03:00
/* todo: make it a define? */
static int
2002-03-11 12:15:32 +03:00
xmlC14NIsXmlNs ( xmlNsPtr ns )
{
return ( ( ns ! = NULL ) & &
( xmlStrEqual ( ns - > prefix , BAD_CAST " xml " ) ) & &
2009-07-09 12:26:22 +04:00
( xmlStrEqual ( ns - > href , XML_XML_NAMESPACE ) ) ) ;
2002-03-04 20:09:44 +03:00
}
/**
2002-06-04 08:27:06 +04:00
* xmlC14NNsCompare :
2002-03-04 20:09:44 +03:00
* @ ns1 : the pointer to first namespace
2012-09-11 09:26:36 +04:00
* @ ns2 : the pointer to second namespace
2002-03-04 20:09:44 +03:00
*
* Compares the namespaces by names ( prefixes ) .
*
* Returns - 1 if ns1 < ns2 , 0 if ns1 = = ns2 or 1 if ns1 > ns2 .
*/
2002-03-11 12:15:32 +03:00
static int
2017-11-09 19:28:00 +03:00
xmlC14NNsCompare ( const void * data1 , const void * data2 )
2002-03-11 12:15:32 +03:00
{
2023-11-22 08:23:00 +03:00
const xmlNs * ns1 = data1 ;
const xmlNs * ns2 = data2 ;
2002-03-11 12:15:32 +03:00
if ( ns1 = = ns2 )
return ( 0 ) ;
if ( ns1 = = NULL )
return ( - 1 ) ;
if ( ns2 = = NULL )
return ( 1 ) ;
return ( xmlStrcmp ( ns1 - > prefix , ns2 - > prefix ) ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NPrintNamespaces :
* @ ns : the pointer to namespace
2012-09-11 09:26:36 +04:00
* @ ctx : the C14N context
2002-03-04 20:09:44 +03:00
*
* Prints the given namespace to the output buffer from C14N context .
*
* Returns 1 on success or 0 on fail .
*/
static int
2023-11-22 08:23:00 +03:00
xmlC14NPrintNamespaces ( const xmlNs * ns , xmlC14NCtxPtr ctx )
2002-03-11 12:15:32 +03:00
{
2002-03-04 20:09:44 +03:00
2002-03-11 12:15:32 +03:00
if ( ( ns = = NULL ) | | ( ctx = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return 0 ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
if ( ns - > prefix ! = NULL ) {
xmlOutputBufferWriteString ( ctx - > buf , " xmlns: " ) ;
xmlOutputBufferWriteString ( ctx - > buf , ( const char * ) ns - > prefix ) ;
2013-05-09 20:02:16 +04:00
xmlOutputBufferWriteString ( ctx - > buf , " = " ) ;
2002-03-04 20:09:44 +03:00
} else {
2013-05-09 20:02:16 +04:00
xmlOutputBufferWriteString ( ctx - > buf , " xmlns= " ) ;
2002-03-04 20:09:44 +03:00
}
2002-06-04 08:27:06 +04:00
if ( ns - > href ! = NULL ) {
2024-02-16 17:42:38 +03:00
xmlOutputBufferWriteQuotedString ( ctx - > buf , ns - > href ) ;
2013-05-09 20:02:16 +04:00
} else {
xmlOutputBufferWriteString ( ctx - > buf , " \" \" " ) ;
2002-06-04 08:27:06 +04:00
}
2002-03-11 12:15:32 +03:00
return ( 1 ) ;
2002-03-04 20:09:44 +03:00
}
2017-11-09 19:28:00 +03:00
static int
xmlC14NPrintNamespacesWalker ( const void * ns , void * ctx ) {
2023-11-22 08:23:00 +03:00
return xmlC14NPrintNamespaces ( ns , ctx ) ;
2017-11-09 19:28:00 +03:00
}
2002-03-04 20:09:44 +03:00
/**
* xmlC14NProcessNamespacesAxis :
2012-09-11 09:26:36 +04:00
* @ ctx : the C14N context
2002-03-04 20:09:44 +03:00
* @ node : the current node
*
* Prints out canonical namespace axis of the current node to the
2012-09-11 09:26:36 +04:00
* buffer from C14N context as follows
2002-03-04 20:09:44 +03:00
*
* Canonical XML v 1.0 ( http : //www.w3.org/TR/xml-c14n)
*
* Namespace Axis
2012-09-11 09:26:36 +04:00
* Consider a list L containing only namespace nodes in the
* axis and in the node - set in lexicographic order ( ascending ) . To begin
* processing L , if the first node is not the default namespace node ( a node
* with no namespace URI and no local name ) , then generate a space followed
2002-03-04 20:09:44 +03:00
* by xmlns = " " if and only if the following conditions are met :
* - the element E that owns the axis is in the node - set
2012-09-11 09:26:36 +04:00
* - The nearest ancestor element of E in the node - set has a default
* namespace node in the node - set ( default namespace nodes always
2002-03-04 20:09:44 +03:00
* have non - empty values in XPath )
2012-09-11 09:26:36 +04:00
* The latter condition eliminates unnecessary occurrences of xmlns = " " in
* the canonical form since an element only receives an xmlns = " " if its
* default namespace is empty and if it has an immediate parent in the
* canonical form that has a non - empty default namespace . To finish
* processing L , simply process every namespace node in L , except omit
* namespace node with local name xml , which defines the xml prefix ,
2002-03-04 20:09:44 +03:00
* if its string value is http : //www.w3.org/XML/1998/namespace.
*
* Exclusive XML Canonicalization v 1.0 ( http : //www.w3.org/TR/xml-exc-c14n)
2012-09-11 09:26:36 +04:00
* Canonical XML applied to a document subset requires the search of the
* ancestor nodes of each orphan element node for attributes in the xml
* namespace , such as xml : lang and xml : space . These are copied into the
* element node except if a declaration of the same attribute is already
* in the attribute axis of the element ( whether or not it is included in
* the document subset ) . This search and copying are omitted from the
2002-03-04 20:09:44 +03:00
* Exclusive XML Canonicalization method .
*
* Returns 0 on success or - 1 on fail .
*/
static int
2002-06-04 08:27:06 +04:00
xmlC14NProcessNamespacesAxis ( xmlC14NCtxPtr ctx , xmlNodePtr cur , int visible )
2002-03-11 12:15:32 +03:00
{
2002-08-01 10:31:50 +04:00
xmlNodePtr n ;
xmlNsPtr ns , tmp ;
2002-03-04 20:09:44 +03:00
xmlListPtr list ;
2002-08-01 10:31:50 +04:00
int already_rendered ;
int has_empty_ns = 0 ;
2012-09-11 09:26:36 +04:00
2002-03-11 12:15:32 +03:00
if ( ( ctx = = NULL ) | | ( cur = = NULL ) | | ( cur - > type ! = XML_ELEMENT_NODE ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
2002-03-04 20:09:44 +03:00
/*
* Create a sorted list to store element namespaces
*/
2017-11-09 19:28:00 +03:00
list = xmlListCreate ( NULL , xmlC14NNsCompare ) ;
2002-03-11 12:15:32 +03:00
if ( list = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
2002-08-01 10:31:50 +04:00
/* check all namespaces */
for ( n = cur ; n ! = NULL ; n = n - > parent ) {
for ( ns = n - > nsDef ; ns ! = NULL ; ns = ns - > next ) {
tmp = xmlSearchNs ( cur - > doc , cur , ns - > prefix ) ;
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
if ( ( tmp = = ns ) & & ! xmlC14NIsXmlNs ( ns ) & & xmlC14NIsVisible ( ctx , ns , cur ) ) {
already_rendered = xmlC14NVisibleNsStackFind ( ctx - > ns_rendered , ns ) ;
if ( visible ) {
2024-02-04 16:08:44 +03:00
if ( xmlC14NVisibleNsStackAdd ( ctx - > ns_rendered , ns , cur ) < 0 ) {
xmlC14NErrMemory ( ctx ) ;
goto error ;
}
2002-08-01 10:31:50 +04:00
}
if ( ! already_rendered ) {
2012-09-11 09:26:36 +04:00
xmlListInsert ( list , ns ) ;
2002-05-31 23:14:57 +04:00
}
2012-09-11 09:26:36 +04:00
if ( xmlStrlen ( ns - > prefix ) = = 0 ) {
2002-08-01 10:31:50 +04:00
has_empty_ns = 1 ;
}
2002-05-31 23:14:57 +04:00
}
2002-05-31 08:24:13 +04:00
}
2002-08-01 10:31:50 +04:00
}
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
/**
2012-09-11 09:26:36 +04:00
* if the first node is not the default namespace node ( a node with no
* namespace URI and no local name ) , then generate a space followed by
2002-08-01 10:31:50 +04:00
* xmlns = " " if and only if the following conditions are met :
* - the element E that owns the axis is in the node - set
2012-09-11 09:26:36 +04:00
* - the nearest ancestor element of E in the node - set has a default
* namespace node in the node - set ( default namespace nodes always
2002-08-01 10:31:50 +04:00
* have non - empty values in XPath )
*/
if ( visible & & ! has_empty_ns ) {
2024-06-11 15:04:38 +03:00
xmlNs ns_default ;
2002-08-01 10:31:50 +04:00
memset ( & ns_default , 0 , sizeof ( ns_default ) ) ;
if ( ! xmlC14NVisibleNsStackFind ( ctx - > ns_rendered , & ns_default ) ) {
2012-09-11 09:26:36 +04:00
xmlC14NPrintNamespaces ( & ns_default , ctx ) ;
2002-06-04 08:27:06 +04:00
}
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/*
* print out all elements from list
2002-03-04 20:09:44 +03:00
*/
2017-11-09 19:28:00 +03:00
xmlListWalk ( list , xmlC14NPrintNamespacesWalker , ( void * ) ctx ) ;
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Cleanup
*/
2024-02-04 16:08:44 +03:00
error :
2002-03-04 20:09:44 +03:00
xmlListDelete ( list ) ;
2002-03-11 12:15:32 +03:00
return ( 0 ) ;
2002-03-04 20:09:44 +03:00
}
2002-05-31 08:24:13 +04:00
2002-03-04 20:09:44 +03:00
/**
* xmlExcC14NProcessNamespacesAxis :
2012-09-11 09:26:36 +04:00
* @ ctx : the C14N context
2002-03-04 20:09:44 +03:00
* @ node : the current node
*
* Prints out exclusive canonical namespace axis of the current node to the
2012-09-11 09:26:36 +04:00
* buffer from C14N context as follows
2002-03-04 20:09:44 +03:00
*
* Exclusive XML Canonicalization
* http : //www.w3.org/TR/xml-exc-c14n
*
2012-09-11 09:26:36 +04:00
* If the element node is in the XPath subset then output the node in
* accordance with Canonical XML except for namespace nodes which are
2002-03-04 20:09:44 +03:00
* rendered as follows :
*
* 1. Render each namespace node iff :
2012-09-11 09:26:36 +04:00
* * it is visibly utilized by the immediate parent element or one of
2002-03-04 20:09:44 +03:00
* its attributes , or is present in InclusiveNamespaces PrefixList , and
2012-09-11 09:26:36 +04:00
* * its prefix and value do not appear in ns_rendered . ns_rendered is
* obtained by popping the state stack in order to obtain a list of
* prefixes and their values which have already been rendered by
2002-03-04 20:09:44 +03:00
* an output ancestor of the namespace node ' s parent element .
2012-09-11 09:26:36 +04:00
* 2. Append the rendered namespace node to the list ns_rendered of namespace
* nodes rendered by output ancestors . Push ns_rendered on state stack and
2002-03-04 20:09:44 +03:00
* recurse .
* 3. After the recursion returns , pop thestate stack .
*
*
* Returns 0 on success or - 1 on fail .
*/
static int
2002-06-04 08:27:06 +04:00
xmlExcC14NProcessNamespacesAxis ( xmlC14NCtxPtr ctx , xmlNodePtr cur , int visible )
2002-03-11 12:15:32 +03:00
{
2002-08-01 10:31:50 +04:00
xmlNsPtr ns ;
2002-03-04 20:09:44 +03:00
xmlListPtr list ;
xmlAttrPtr attr ;
2002-08-01 10:31:50 +04:00
int already_rendered ;
int has_empty_ns = 0 ;
int has_visibly_utilized_empty_ns = 0 ;
int has_empty_ns_in_inclusive_list = 0 ;
2012-09-11 09:26:36 +04:00
2002-03-11 12:15:32 +03:00
if ( ( ctx = = NULL ) | | ( cur = = NULL ) | | ( cur - > type ! = XML_ELEMENT_NODE ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
2009-07-09 12:26:22 +04:00
if ( ! xmlC14NIsExclusive ( ctx ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
2002-03-04 20:09:44 +03:00
/*
* Create a sorted list to store element namespaces
*/
2017-11-09 19:28:00 +03:00
list = xmlListCreate ( NULL , xmlC14NNsCompare ) ;
2002-03-11 12:15:32 +03:00
if ( list = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
2002-03-04 20:09:44 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-08-01 10:31:50 +04:00
* process inclusive namespaces :
2012-09-11 09:26:36 +04:00
* All namespace nodes appearing on inclusive ns list are
2002-08-01 10:31:50 +04:00
* handled as provided in Canonical XML
2002-03-04 20:09:44 +03:00
*/
2002-08-01 10:31:50 +04:00
if ( ctx - > inclusive_ns_prefixes ! = NULL ) {
2012-09-11 09:26:36 +04:00
xmlChar * prefix ;
2002-08-01 10:31:50 +04:00
int i ;
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
for ( i = 0 ; ctx - > inclusive_ns_prefixes [ i ] ! = NULL ; + + i ) {
prefix = ctx - > inclusive_ns_prefixes [ i ] ;
/*
* Special values for namespace with empty prefix
*/
if ( xmlStrEqual ( prefix , BAD_CAST " #default " )
| | xmlStrEqual ( prefix , BAD_CAST " " ) ) {
prefix = NULL ;
has_empty_ns_in_inclusive_list = 1 ;
}
2012-09-11 09:26:36 +04:00
ns = xmlSearchNs ( cur - > doc , cur , prefix ) ;
2002-08-01 10:31:50 +04:00
if ( ( ns ! = NULL ) & & ! xmlC14NIsXmlNs ( ns ) & & xmlC14NIsVisible ( ctx , ns , cur ) ) {
already_rendered = xmlC14NVisibleNsStackFind ( ctx - > ns_rendered , ns ) ;
if ( visible ) {
2024-02-04 16:08:44 +03:00
if ( xmlC14NVisibleNsStackAdd ( ctx - > ns_rendered , ns , cur ) < 0 ) {
xmlC14NErrMemory ( ctx ) ;
goto error ;
}
2002-08-01 10:31:50 +04:00
}
if ( ! already_rendered ) {
2012-09-11 09:26:36 +04:00
xmlListInsert ( list , ns ) ;
2002-08-01 10:31:50 +04:00
}
2012-09-11 09:26:36 +04:00
if ( xmlStrlen ( ns - > prefix ) = = 0 ) {
2002-08-01 10:31:50 +04:00
has_empty_ns = 1 ;
}
2002-06-04 08:27:06 +04:00
}
2002-08-01 10:31:50 +04:00
}
}
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
/* add node namespace */
if ( cur - > ns ! = NULL ) {
ns = cur - > ns ;
} else {
ns = xmlSearchNs ( cur - > doc , cur , NULL ) ;
has_visibly_utilized_empty_ns = 1 ;
}
if ( ( ns ! = NULL ) & & ! xmlC14NIsXmlNs ( ns ) ) {
2012-09-11 09:26:36 +04:00
if ( visible & & xmlC14NIsVisible ( ctx , ns , cur ) ) {
2002-08-01 10:31:50 +04:00
if ( ! xmlExcC14NVisibleNsStackFind ( ctx - > ns_rendered , ns , ctx ) ) {
xmlListInsert ( list , ns ) ;
2002-06-04 08:27:06 +04:00
}
2002-05-31 23:14:57 +04:00
}
2002-08-01 10:31:50 +04:00
if ( visible ) {
2024-02-04 16:08:44 +03:00
if ( xmlC14NVisibleNsStackAdd ( ctx - > ns_rendered , ns , cur ) < 0 ) {
xmlC14NErrMemory ( ctx ) ;
goto error ;
}
2002-08-01 10:31:50 +04:00
}
if ( xmlStrlen ( ns - > prefix ) = = 0 ) {
has_empty_ns = 1 ;
}
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
/* add attributes */
for ( attr = cur - > properties ; attr ! = NULL ; attr = attr - > next ) {
2012-09-11 09:26:36 +04:00
/*
2002-03-17 13:34:11 +03:00
* we need to check that attribute is visible and has non
2012-09-11 09:26:36 +04:00
* default namespace ( XML Namespaces : " default namespaces
* do not apply directly to attributes " )
2002-03-11 12:15:32 +03:00
*/
2005-06-06 21:16:50 +04:00
if ( ( attr - > ns ! = NULL ) & & ! xmlC14NIsXmlNs ( attr - > ns ) & & xmlC14NIsVisible ( ctx , attr , cur ) ) {
2002-08-01 10:31:50 +04:00
already_rendered = xmlExcC14NVisibleNsStackFind ( ctx - > ns_rendered , attr - > ns , ctx ) ;
2024-02-04 16:08:44 +03:00
if ( xmlC14NVisibleNsStackAdd ( ctx - > ns_rendered , attr - > ns , cur ) < 0 ) {
xmlC14NErrMemory ( ctx ) ;
goto error ;
}
2002-08-01 10:31:50 +04:00
if ( ! already_rendered & & visible ) {
2012-09-11 09:26:36 +04:00
xmlListInsert ( list , attr - > ns ) ;
2002-08-01 10:31:50 +04:00
}
if ( xmlStrlen ( attr - > ns - > prefix ) = = 0 ) {
has_empty_ns = 1 ;
}
2005-10-28 07:15:18 +04:00
} else if ( ( attr - > ns ! = NULL ) & & ( xmlStrlen ( attr - > ns - > prefix ) = = 0 ) & & ( xmlStrlen ( attr - > ns - > href ) = = 0 ) ) {
2002-08-01 10:31:50 +04:00
has_visibly_utilized_empty_ns = 1 ;
}
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
2002-08-01 10:31:50 +04:00
/*
* Process xmlns = " "
2002-03-04 20:09:44 +03:00
*/
2012-09-11 09:26:36 +04:00
if ( visible & & has_visibly_utilized_empty_ns & &
2002-08-01 10:31:50 +04:00
! has_empty_ns & & ! has_empty_ns_in_inclusive_list ) {
2024-06-11 15:04:38 +03:00
xmlNs ns_default ;
2002-03-11 12:15:32 +03:00
2002-08-01 10:31:50 +04:00
memset ( & ns_default , 0 , sizeof ( ns_default ) ) ;
2012-09-11 09:26:36 +04:00
2002-08-01 10:31:50 +04:00
already_rendered = xmlExcC14NVisibleNsStackFind ( ctx - > ns_rendered , & ns_default , ctx ) ;
if ( ! already_rendered ) {
2012-09-11 09:26:36 +04:00
xmlC14NPrintNamespaces ( & ns_default , ctx ) ;
2002-08-01 10:31:50 +04:00
}
} else if ( visible & & ! has_empty_ns & & has_empty_ns_in_inclusive_list ) {
2024-06-11 15:04:38 +03:00
xmlNs ns_default ;
2002-08-01 10:31:50 +04:00
memset ( & ns_default , 0 , sizeof ( ns_default ) ) ;
if ( ! xmlC14NVisibleNsStackFind ( ctx - > ns_rendered , & ns_default ) ) {
2012-09-11 09:26:36 +04:00
xmlC14NPrintNamespaces ( & ns_default , ctx ) ;
2002-08-01 10:31:50 +04:00
}
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
2002-08-01 10:31:50 +04:00
2012-09-11 09:26:36 +04:00
/*
* print out all elements from list
2002-03-04 20:09:44 +03:00
*/
2017-11-09 19:28:00 +03:00
xmlListWalk ( list , xmlC14NPrintNamespacesWalker , ( void * ) ctx ) ;
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Cleanup
*/
2024-02-04 16:08:44 +03:00
error :
2002-03-04 20:09:44 +03:00
xmlListDelete ( list ) ;
2002-03-11 12:15:32 +03:00
return ( 0 ) ;
2002-03-04 20:09:44 +03:00
}
2009-07-09 12:26:22 +04:00
/**
* xmlC14NIsXmlAttr :
2012-09-11 09:26:36 +04:00
* @ attr : the attr to check
*
2009-07-09 12:26:22 +04:00
* Checks whether the given attribute is a default " xml: " namespace
* with href = " http://www.w3.org/XML/1998/namespace "
*
* Returns 1 if the node is default or 0 otherwise
*/
/* todo: make it a define? */
static int
xmlC14NIsXmlAttr ( xmlAttrPtr attr )
{
2012-09-11 09:26:36 +04:00
return ( ( attr - > ns ! = NULL ) & &
2009-07-09 12:26:22 +04:00
( xmlC14NIsXmlNs ( attr - > ns ) ! = 0 ) ) ;
}
2002-03-04 20:09:44 +03:00
/**
* xmlC14NAttrsCompare :
2002-06-04 08:27:06 +04:00
* @ attr1 : the pointer tls o first attr
2012-09-11 09:26:36 +04:00
* @ attr2 : the pointer to second attr
2002-03-04 20:09:44 +03:00
*
* Prints the given attribute to the output buffer from C14N context .
*
* Returns - 1 if attr1 < attr2 , 0 if attr1 = = attr2 or 1 if attr1 > attr2 .
*/
static int
2017-11-09 19:28:00 +03:00
xmlC14NAttrsCompare ( const void * data1 , const void * data2 )
2002-03-11 12:15:32 +03:00
{
2023-11-22 08:23:00 +03:00
const xmlAttr * attr1 = data1 ;
const xmlAttr * attr2 = data2 ;
2002-03-04 20:09:44 +03:00
int ret = 0 ;
/*
* Simple cases
*/
2002-03-11 12:15:32 +03:00
if ( attr1 = = attr2 )
return ( 0 ) ;
if ( attr1 = = NULL )
return ( - 1 ) ;
if ( attr2 = = NULL )
return ( 1 ) ;
if ( attr1 - > ns = = attr2 - > ns ) {
return ( xmlStrcmp ( attr1 - > name , attr2 - > name ) ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Attributes in the default namespace are first
* because the default namespace is not applied to
* unqualified attributes
*/
2002-03-11 12:15:32 +03:00
if ( attr1 - > ns = = NULL )
return ( - 1 ) ;
if ( attr2 - > ns = = NULL )
return ( 1 ) ;
if ( attr1 - > ns - > prefix = = NULL )
return ( - 1 ) ;
if ( attr2 - > ns - > prefix = = NULL )
return ( 1 ) ;
2002-03-04 20:09:44 +03:00
ret = xmlStrcmp ( attr1 - > ns - > href , attr2 - > ns - > href ) ;
2002-03-11 12:15:32 +03:00
if ( ret = = 0 ) {
ret = xmlStrcmp ( attr1 - > name , attr2 - > name ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
return ( ret ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NPrintAttrs :
* @ attr : the pointer to attr
2012-09-11 09:26:36 +04:00
* @ ctx : the C14N context
2002-03-04 20:09:44 +03:00
*
* Prints out canonical attribute urrent node to the
2012-09-11 09:26:36 +04:00
* buffer from C14N context as follows
2002-03-04 20:09:44 +03:00
*
* Canonical XML v 1.0 ( http : //www.w3.org/TR/xml-c14n)
*
* Returns 1 on success or 0 on fail .
*/
static int
2017-11-09 19:28:00 +03:00
xmlC14NPrintAttrs ( const void * data , void * user )
2002-03-11 12:15:32 +03:00
{
2023-11-22 08:23:00 +03:00
const xmlAttr * attr = data ;
2017-11-09 19:28:00 +03:00
xmlC14NCtxPtr ctx = ( xmlC14NCtxPtr ) user ;
2002-03-04 20:09:44 +03:00
xmlChar * value ;
xmlChar * buffer ;
2002-03-11 12:15:32 +03:00
if ( ( attr = = NULL ) | | ( ctx = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( 0 ) ;
2002-03-04 20:09:44 +03:00
}
xmlOutputBufferWriteString ( ctx - > buf , " " ) ;
2002-03-11 12:15:32 +03:00
if ( attr - > ns ! = NULL & & xmlStrlen ( attr - > ns - > prefix ) > 0 ) {
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) attr - > ns - > prefix ) ;
xmlOutputBufferWriteString ( ctx - > buf , " : " ) ;
2002-03-04 20:09:44 +03:00
}
xmlOutputBufferWriteString ( ctx - > buf , ( const char * ) attr - > name ) ;
xmlOutputBufferWriteString ( ctx - > buf , " = \" " ) ;
2009-07-09 12:26:22 +04:00
value = xmlNodeListGetString ( ctx - > doc , attr - > children , 1 ) ;
2002-03-04 20:09:44 +03:00
/* todo: should we log an error if value==NULL ? */
2002-03-11 12:15:32 +03:00
if ( value ! = NULL ) {
buffer = xmlC11NNormalizeAttr ( value ) ;
xmlFree ( value ) ;
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( ctx - > buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
} else {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( 0 ) ;
}
2002-03-04 20:09:44 +03:00
}
xmlOutputBufferWriteString ( ctx - > buf , " \" " ) ;
2002-03-11 12:15:32 +03:00
return ( 1 ) ;
2002-03-04 20:09:44 +03:00
}
2009-07-09 12:26:22 +04:00
/**
* xmlC14NFindHiddenParentAttr :
*
* Finds an attribute in a hidden parent node .
2012-09-11 09:26:36 +04:00
*
2009-07-09 12:26:22 +04:00
* Returns a pointer to the attribute node ( if found ) or NULL otherwise .
*/
static xmlAttrPtr
xmlC14NFindHiddenParentAttr ( xmlC14NCtxPtr ctx , xmlNodePtr cur , const xmlChar * name , const xmlChar * ns )
{
xmlAttrPtr res ;
while ( ( cur ! = NULL ) & & ( ! xmlC14NIsVisible ( ctx , cur , cur - > parent ) ) ) {
res = xmlHasNsProp ( cur , name , ns ) ;
if ( res ! = NULL ) {
return res ;
}
cur = cur - > parent ;
}
return NULL ;
}
/**
* xmlC14NFixupBaseAttr :
*
* Fixes up the xml : base attribute
*
* Returns the newly created attribute or NULL
*/
static xmlAttrPtr
xmlC14NFixupBaseAttr ( xmlC14NCtxPtr ctx , xmlAttrPtr xml_base_attr )
2012-09-11 09:26:36 +04:00
{
2009-07-09 12:26:22 +04:00
xmlChar * res = NULL ;
xmlNodePtr cur ;
xmlAttrPtr attr ;
xmlChar * tmp_str ;
xmlChar * tmp_str2 ;
int tmp_str_len ;
if ( ( ctx = = NULL ) | | ( xml_base_attr = = NULL ) | | ( xml_base_attr - > parent = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2009-07-09 12:26:22 +04:00
return ( NULL ) ;
}
/* start from current value */
res = xmlNodeListGetString ( ctx - > doc , xml_base_attr - > children , 1 ) ;
if ( res = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2009-07-09 12:26:22 +04:00
return ( NULL ) ;
}
/* go up the stack until we find a node that we rendered already */
cur = xml_base_attr - > parent - > parent ;
while ( ( cur ! = NULL ) & & ( ! xmlC14NIsVisible ( ctx , cur , cur - > parent ) ) ) {
2024-02-04 16:08:44 +03:00
int code ;
2009-07-09 12:26:22 +04:00
attr = xmlHasNsProp ( cur , BAD_CAST " base " , XML_XML_NAMESPACE ) ;
if ( attr ! = NULL ) {
/* get attr value */
tmp_str = xmlNodeListGetString ( ctx - > doc , attr - > children , 1 ) ;
if ( tmp_str = = NULL ) {
xmlFree ( res ) ;
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2009-07-09 12:26:22 +04:00
return ( NULL ) ;
2012-09-11 09:26:36 +04:00
}
2009-07-09 12:26:22 +04:00
2012-09-11 09:26:36 +04:00
/* we need to add '/' if our current base uri ends with '..' or '.'
2009-07-09 12:26:22 +04:00
to ensure that we are forced to go " up " all the time */
tmp_str_len = xmlStrlen ( tmp_str ) ;
if ( tmp_str_len > 1 & & tmp_str [ tmp_str_len - 2 ] = = ' . ' ) {
tmp_str2 = xmlStrcat ( tmp_str , BAD_CAST " / " ) ;
if ( tmp_str2 = = NULL ) {
xmlFree ( tmp_str ) ;
xmlFree ( res ) ;
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2009-07-09 12:26:22 +04:00
return ( NULL ) ;
}
tmp_str = tmp_str2 ;
}
/* build uri */
2024-02-04 16:08:44 +03:00
code = xmlBuildURISafe ( res , tmp_str , & tmp_str2 ) ;
if ( code ! = 0 ) {
2009-07-09 12:26:22 +04:00
xmlFree ( tmp_str ) ;
xmlFree ( res ) ;
2024-02-04 16:08:44 +03:00
if ( code < 0 )
xmlC14NErrMemory ( ctx ) ;
else
xmlC14NErr ( ctx , cur , XML_ERR_INVALID_URI ,
" processing xml:base attribute - "
" can't construct uri " ) ;
2009-07-09 12:26:22 +04:00
return ( NULL ) ;
}
/* cleanup and set the new res */
xmlFree ( tmp_str ) ;
xmlFree ( res ) ;
res = tmp_str2 ;
}
/* next */
cur = cur - > parent ;
}
/* check if result uri is empty or not */
if ( ( res = = NULL ) | | xmlStrEqual ( res , BAD_CAST " " ) ) {
xmlFree ( res ) ;
return ( NULL ) ;
}
/* create and return the new attribute node */
attr = xmlNewNsProp ( NULL , xml_base_attr - > ns , BAD_CAST " base " , res ) ;
if ( attr = = NULL ) {
xmlFree ( res ) ;
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2009-07-09 12:26:22 +04:00
return ( NULL ) ;
}
2012-09-11 09:26:36 +04:00
2009-07-09 12:26:22 +04:00
/* done */
xmlFree ( res ) ;
return ( attr ) ;
}
2002-03-04 20:09:44 +03:00
/**
* xmlC14NProcessAttrsAxis :
2012-09-11 09:26:36 +04:00
* @ ctx : the C14N context
2002-03-04 20:09:44 +03:00
* @ cur : the current node
2005-06-07 20:53:57 +04:00
* @ parent_visible : the visibility of parent node
2009-07-09 12:26:22 +04:00
* @ all_parents_visible : the visibility of all parent nodes
2002-03-04 20:09:44 +03:00
*
* Prints out canonical attribute axis of the current node to the
2012-09-11 09:26:36 +04:00
* buffer from C14N context as follows
2002-03-04 20:09:44 +03:00
*
* Canonical XML v 1.0 ( http : //www.w3.org/TR/xml-c14n)
*
2012-09-11 09:26:36 +04:00
* Attribute Axis
* In lexicographic order ( ascending ) , process each node that
2002-03-04 20:09:44 +03:00
* is in the element ' s attribute axis and in the node - set .
2012-09-11 09:26:36 +04:00
*
* The processing of an element node E MUST be modified slightly
* when an XPath node - set is given as input and the element ' s
2002-03-04 20:09:44 +03:00
* parent is omitted from the node - set .
*
*
* Exclusive XML Canonicalization v 1.0 ( http : //www.w3.org/TR/xml-exc-c14n)
*
2012-09-11 09:26:36 +04:00
* Canonical XML applied to a document subset requires the search of the
* ancestor nodes of each orphan element node for attributes in the xml
* namespace , such as xml : lang and xml : space . These are copied into the
* element node except if a declaration of the same attribute is already
* in the attribute axis of the element ( whether or not it is included in
* the document subset ) . This search and copying are omitted from the
2002-03-04 20:09:44 +03:00
* Exclusive XML Canonicalization method .
*
* Returns 0 on success or - 1 on fail .
*/
static int
2005-06-07 20:53:57 +04:00
xmlC14NProcessAttrsAxis ( xmlC14NCtxPtr ctx , xmlNodePtr cur , int parent_visible )
2002-03-11 12:15:32 +03:00
{
2002-03-04 20:09:44 +03:00
xmlAttrPtr attr ;
2012-09-11 09:26:36 +04:00
xmlListPtr list ;
2009-07-09 12:26:22 +04:00
xmlAttrPtr attrs_to_delete = NULL ;
2012-09-11 09:26:36 +04:00
2009-07-09 12:26:22 +04:00
/* special processing for 1.1 spec */
xmlAttrPtr xml_base_attr = NULL ;
xmlAttrPtr xml_lang_attr = NULL ;
xmlAttrPtr xml_space_attr = NULL ;
2002-03-11 12:15:32 +03:00
if ( ( ctx = = NULL ) | | ( cur = = NULL ) | | ( cur - > type ! = XML_ELEMENT_NODE ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
2002-03-04 20:09:44 +03:00
/*
* Create a sorted list to store element attributes
*/
2017-11-09 19:28:00 +03:00
list = xmlListCreate ( NULL , xmlC14NAttrsCompare ) ;
2002-03-11 12:15:32 +03:00
if ( list = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2009-07-09 12:26:22 +04:00
switch ( ctx - > mode ) {
case XML_C14N_1_0 :
2012-09-11 09:26:36 +04:00
/* The processing of an element node E MUST be modified slightly when an XPath node-set is
* given as input and the element ' s parent is omitted from the node - set . The method for processing
* the attribute axis of an element E in the node - set is enhanced . All element nodes along E ' s
* ancestor axis are examined for nearest occurrences of attributes in the xml namespace , such
* as xml : lang and xml : space ( whether or not they are in the node - set ) . From this list of attributes ,
* remove any that are in E ' s attribute axis ( whether or not they are in the node - set ) . Then ,
* lexicographically merge this attribute list with the nodes of E ' s attribute axis that are in
* the node - set . The result of visiting the attribute axis is computed by processing the attribute
* nodes in this merged attribute list .
2009-07-09 12:26:22 +04:00
*/
2012-09-11 09:26:36 +04:00
/*
* Add all visible attributes from current node .
2009-07-09 12:26:22 +04:00
*/
attr = cur - > properties ;
while ( attr ! = NULL ) {
/* check that attribute is visible */
if ( xmlC14NIsVisible ( ctx , attr , cur ) ) {
xmlListInsert ( list , attr ) ;
}
attr = attr - > next ;
2002-03-11 12:15:32 +03:00
}
2012-09-11 09:26:36 +04:00
/*
2009-07-09 12:26:22 +04:00
* Handle xml attributes
2002-03-11 12:15:32 +03:00
*/
2012-09-11 09:26:36 +04:00
if ( parent_visible & & ( cur - > parent ! = NULL ) & &
( ! xmlC14NIsVisible ( ctx , cur - > parent , cur - > parent - > parent ) ) )
2009-07-09 12:26:22 +04:00
{
xmlNodePtr tmp ;
/*
2012-09-11 09:26:36 +04:00
* If XPath node - set is not specified then the parent is always
2009-07-09 12:26:22 +04:00
* visible !
*/
tmp = cur - > parent ;
while ( tmp ! = NULL ) {
attr = tmp - > properties ;
while ( attr ! = NULL ) {
if ( xmlC14NIsXmlAttr ( attr ) ! = 0 ) {
if ( xmlListSearch ( list , attr ) = = NULL ) {
xmlListInsert ( list , attr ) ;
}
2002-03-11 12:15:32 +03:00
}
2009-07-09 12:26:22 +04:00
attr = attr - > next ;
}
tmp = tmp - > parent ;
}
}
/* done */
break ;
case XML_C14N_EXCLUSIVE_1_0 :
2012-09-11 09:26:36 +04:00
/* attributes in the XML namespace, such as xml:lang and xml:space
* are not imported into orphan nodes of the document subset
2009-07-09 12:26:22 +04:00
*/
2012-09-11 09:26:36 +04:00
/*
* Add all visible attributes from current node .
2009-07-09 12:26:22 +04:00
*/
attr = cur - > properties ;
while ( attr ! = NULL ) {
/* check that attribute is visible */
if ( xmlC14NIsVisible ( ctx , attr , cur ) ) {
xmlListInsert ( list , attr ) ;
}
attr = attr - > next ;
}
/* do nothing special for xml attributes */
break ;
case XML_C14N_1_1 :
2012-09-11 09:26:36 +04:00
/* The processing of an element node E MUST be modified slightly when an XPath node-set is
* given as input and some of the element ' s ancestors are omitted from the node - set .
2009-07-09 12:26:22 +04:00
*
2012-09-11 09:26:36 +04:00
* Simple inheritable attributes are attributes that have a value that requires at most a simple
* redeclaration . This redeclaration is done by supplying a new value in the child axis . The
* redeclaration of a simple inheritable attribute A contained in one of E ' s ancestors is done
* by supplying a value to an attribute Ae inside E with the same name . Simple inheritable attributes
2009-07-09 12:26:22 +04:00
* are xml : lang and xml : space .
2012-09-11 09:26:36 +04:00
*
* The method for processing the attribute axis of an element E in the node - set is hence enhanced .
* All element nodes along E ' s ancestor axis are examined for the nearest occurrences of simple
* inheritable attributes in the xml namespace , such as xml : lang and xml : space ( whether or not they
* are in the node - set ) . From this list of attributes , any simple inheritable attributes that are
* already in E ' s attribute axis ( whether or not they are in the node - set ) are removed . Then ,
* lexicographically merge this attribute list with the nodes of E ' s attribute axis that are in
* the node - set . The result of visiting the attribute axis is computed by processing the attribute
2009-07-09 12:26:22 +04:00
* nodes in this merged attribute list .
2012-09-11 09:26:36 +04:00
*
* The xml : id attribute is not a simple inheritable attribute and no processing of these attributes is
2009-07-09 12:26:22 +04:00
* performed .
2012-09-11 09:26:36 +04:00
*
* The xml : base attribute is not a simple inheritable attribute and requires special processing beyond
2009-07-09 12:26:22 +04:00
* a simple redeclaration .
2012-09-11 09:26:36 +04:00
*
* Attributes in the XML namespace other than xml : base , xml : id , xml : lang , and xml : space MUST be processed
2009-07-09 12:26:22 +04:00
* as ordinary attributes .
*/
2012-09-11 09:26:36 +04:00
/*
* Add all visible attributes from current node .
2009-07-09 12:26:22 +04:00
*/
attr = cur - > properties ;
while ( attr ! = NULL ) {
/* special processing for XML attribute kiks in only when we have invisible parents */
if ( ( ! parent_visible ) | | ( xmlC14NIsXmlAttr ( attr ) = = 0 ) ) {
/* check that attribute is visible */
if ( xmlC14NIsVisible ( ctx , attr , cur ) ) {
xmlListInsert ( list , attr ) ;
}
} else {
int matched = 0 ;
/* check for simple inheritance attributes */
if ( ( ! matched ) & & ( xml_lang_attr = = NULL ) & & xmlStrEqual ( attr - > name , BAD_CAST " lang " ) ) {
xml_lang_attr = attr ;
matched = 1 ;
2012-09-11 09:26:36 +04:00
}
2009-07-09 12:26:22 +04:00
if ( ( ! matched ) & & ( xml_space_attr = = NULL ) & & xmlStrEqual ( attr - > name , BAD_CAST " space " ) ) {
xml_space_attr = attr ;
matched = 1 ;
}
/* check for base attr */
if ( ( ! matched ) & & ( xml_base_attr = = NULL ) & & xmlStrEqual ( attr - > name , BAD_CAST " base " ) ) {
xml_base_attr = attr ;
matched = 1 ;
}
/* otherwise, it is a normal attribute, so just check if it is visible */
if ( ( ! matched ) & & xmlC14NIsVisible ( ctx , attr , cur ) ) {
xmlListInsert ( list , attr ) ;
2002-03-11 12:15:32 +03:00
}
}
2012-09-11 09:26:36 +04:00
2009-07-09 12:26:22 +04:00
/* move to the next one */
attr = attr - > next ;
2002-03-11 12:15:32 +03:00
}
2012-09-11 09:26:36 +04:00
2009-07-09 12:26:22 +04:00
/* special processing for XML attribute kiks in only when we have invisible parents */
if ( ( parent_visible ) ) {
/* simple inheritance attributes - copy */
if ( xml_lang_attr = = NULL ) {
xml_lang_attr = xmlC14NFindHiddenParentAttr ( ctx , cur - > parent , BAD_CAST " lang " , XML_XML_NAMESPACE ) ;
}
if ( xml_lang_attr ! = NULL ) {
xmlListInsert ( list , xml_lang_attr ) ;
}
if ( xml_space_attr = = NULL ) {
xml_space_attr = xmlC14NFindHiddenParentAttr ( ctx , cur - > parent , BAD_CAST " space " , XML_XML_NAMESPACE ) ;
}
if ( xml_space_attr ! = NULL ) {
xmlListInsert ( list , xml_space_attr ) ;
}
/* base uri attribute - fix up */
if ( xml_base_attr = = NULL ) {
/* if we don't have base uri attribute, check if we have a "hidden" one above */
xml_base_attr = xmlC14NFindHiddenParentAttr ( ctx , cur - > parent , BAD_CAST " base " , XML_XML_NAMESPACE ) ;
}
if ( xml_base_attr ! = NULL ) {
xml_base_attr = xmlC14NFixupBaseAttr ( ctx , xml_base_attr ) ;
2012-09-11 09:26:36 +04:00
if ( xml_base_attr ! = NULL ) {
2009-07-09 12:26:22 +04:00
xmlListInsert ( list , xml_base_attr ) ;
/* note that we MUST delete returned attr node ourselves! */
xml_base_attr - > next = attrs_to_delete ;
attrs_to_delete = xml_base_attr ;
}
}
}
/* done */
break ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
/*
* print out all elements from list
2002-03-04 20:09:44 +03:00
*/
2017-11-09 19:28:00 +03:00
xmlListWalk ( list , xmlC14NPrintAttrs , ( void * ) ctx ) ;
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Cleanup
*/
2009-07-09 12:26:22 +04:00
xmlFreePropList ( attrs_to_delete ) ;
2002-03-11 12:15:32 +03:00
xmlListDelete ( list ) ;
return ( 0 ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/**
2002-03-04 20:09:44 +03:00
* xmlC14NCheckForRelativeNamespaces :
* @ ctx : the C14N context
* @ cur : the current element node
*
* Checks that current element node has no relative namespaces defined
*
* Returns 0 if the node has no relative namespaces or - 1 otherwise .
*/
static int
2002-03-11 12:15:32 +03:00
xmlC14NCheckForRelativeNamespaces ( xmlC14NCtxPtr ctx , xmlNodePtr cur )
{
2002-03-04 20:09:44 +03:00
xmlNsPtr ns ;
2002-03-11 12:15:32 +03:00
if ( ( ctx = = NULL ) | | ( cur = = NULL ) | | ( cur - > type ! = XML_ELEMENT_NODE ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
ns = cur - > nsDef ;
while ( ns ! = NULL ) {
if ( xmlStrlen ( ns - > href ) > 0 ) {
xmlURIPtr uri ;
2024-02-04 16:08:44 +03:00
int code ;
2002-03-11 12:15:32 +03:00
2024-02-04 16:08:44 +03:00
code = xmlParseURISafe ( ( const char * ) ns - > href , & uri ) ;
2002-03-11 12:15:32 +03:00
if ( uri = = NULL ) {
2024-02-04 16:08:44 +03:00
if ( code < 0 )
xmlC14NErrMemory ( ctx ) ;
else
xmlC14NErr ( ctx , cur , XML_ERR_INVALID_URI ,
" parsing namespace uri " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
if ( xmlStrlen ( ( const xmlChar * ) uri - > scheme ) = = 0 ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrRelativeNamespace ( ctx , uri - > scheme ) ;
2002-03-11 12:15:32 +03:00
xmlFreeURI ( uri ) ;
return ( - 1 ) ;
}
xmlFreeURI ( uri ) ;
}
ns = ns - > next ;
}
return ( 0 ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NProcessElementNode :
2012-09-11 09:26:36 +04:00
* @ ctx : the pointer to C14N context object
2002-03-04 20:09:44 +03:00
* @ cur : the node to process
2009-07-09 12:26:22 +04:00
* @ visible : this node is visible
* @ all_parents_visible : whether all the parents of this node are visible
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Canonical XML v 1.0 ( http : //www.w3.org/TR/xml-c14n)
*
* Element Nodes
2012-09-11 09:26:36 +04:00
* If the element is not in the node - set , then the result is obtained
* by processing the namespace axis , then the attribute axis , then
* processing the child nodes of the element that are in the node - set
* ( in document order ) . If the element is in the node - set , then the result
* is an open angle bracket ( < ) , the element QName , the result of
* processing the namespace axis , the result of processing the attribute
* axis , a close angle bracket ( > ) , the result of processing the child
* nodes of the element that are in the node - set ( in document order ) , an
* open angle bracket , a forward slash ( / ) , the element QName , and a close
2002-03-04 20:09:44 +03:00
* angle bracket .
*
* Returns non - negative value on success or negative value on fail
*/
static int
2002-03-11 12:15:32 +03:00
xmlC14NProcessElementNode ( xmlC14NCtxPtr ctx , xmlNodePtr cur , int visible )
{
2002-03-04 20:09:44 +03:00
int ret ;
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStack state ;
2002-03-15 12:42:33 +03:00
int parent_is_doc = 0 ;
2002-03-04 20:09:44 +03:00
2002-03-11 12:15:32 +03:00
if ( ( ctx = = NULL ) | | ( cur = = NULL ) | | ( cur - > type ! = XML_ELEMENT_NODE ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
2002-03-04 20:09:44 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Check relative relative namespaces :
* implementations of XML canonicalization MUST report an operation
* failure on documents containing relative namespace URIs .
*/
2024-02-04 16:08:44 +03:00
if ( xmlC14NCheckForRelativeNamespaces ( ctx , cur ) < 0 )
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-06-04 08:27:06 +04:00
* Save ns_rendered stack position
2002-03-04 20:09:44 +03:00
*/
2006-03-10 16:40:16 +03:00
memset ( & state , 0 , sizeof ( state ) ) ;
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStackSave ( ctx - > ns_rendered , & state ) ;
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
if ( visible ) {
2002-03-11 12:15:32 +03:00
if ( ctx - > parent_is_doc ) {
2002-03-15 12:42:33 +03:00
/* save this flag into the stack */
parent_is_doc = ctx - > parent_is_doc ;
ctx - > parent_is_doc = 0 ;
2002-03-11 12:15:32 +03:00
ctx - > pos = XMLC14N_INSIDE_DOCUMENT_ELEMENT ;
}
xmlOutputBufferWriteString ( ctx - > buf , " < " ) ;
if ( ( cur - > ns ! = NULL ) & & ( xmlStrlen ( cur - > ns - > prefix ) > 0 ) ) {
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( ctx - > buf , " : " ) ;
}
xmlOutputBufferWriteString ( ctx - > buf , ( const char * ) cur - > name ) ;
2002-06-04 08:27:06 +04:00
}
2002-03-11 12:15:32 +03:00
2009-07-09 12:26:22 +04:00
if ( ! xmlC14NIsExclusive ( ctx ) ) {
2002-06-04 08:27:06 +04:00
ret = xmlC14NProcessNamespacesAxis ( ctx , cur , visible ) ;
} else {
ret = xmlExcC14NProcessNamespacesAxis ( ctx , cur , visible ) ;
}
2024-02-04 16:08:44 +03:00
if ( ret < 0 )
2002-06-04 08:27:06 +04:00
return ( - 1 ) ;
/* todo: shouldn't this go to "visible only"? */
if ( visible ) {
xmlC14NVisibleNsStackShift ( ctx - > ns_rendered ) ;
}
2012-09-11 09:26:36 +04:00
2005-06-07 20:53:57 +04:00
ret = xmlC14NProcessAttrsAxis ( ctx , cur , visible ) ;
2024-02-04 16:08:44 +03:00
if ( ret < 0 )
2012-09-11 09:26:36 +04:00
return ( - 1 ) ;
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
if ( visible ) {
2002-03-11 12:15:32 +03:00
xmlOutputBufferWriteString ( ctx - > buf , " > " ) ;
2002-03-04 20:09:44 +03:00
}
if ( cur - > children ! = NULL ) {
2002-03-11 12:15:32 +03:00
ret = xmlC14NProcessNodeList ( ctx , cur - > children ) ;
2024-02-04 16:08:44 +03:00
if ( ret < 0 )
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
if ( visible ) {
xmlOutputBufferWriteString ( ctx - > buf , " </ " ) ;
if ( ( cur - > ns ! = NULL ) & & ( xmlStrlen ( cur - > ns - > prefix ) > 0 ) ) {
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( ctx - > buf , " : " ) ;
}
xmlOutputBufferWriteString ( ctx - > buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( ctx - > buf , " > " ) ;
2002-03-15 12:42:33 +03:00
if ( parent_is_doc ) {
/* restore this flag from the stack for next node */
ctx - > parent_is_doc = parent_is_doc ;
ctx - > pos = XMLC14N_AFTER_DOCUMENT_ELEMENT ;
2002-03-11 12:15:32 +03:00
}
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/*
2002-06-04 08:27:06 +04:00
* Restore ns_rendered stack position
2002-03-04 20:09:44 +03:00
*/
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStackRestore ( ctx - > ns_rendered , & state ) ;
2002-03-11 12:15:32 +03:00
return ( 0 ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NProcessNode :
2012-09-11 09:26:36 +04:00
* @ ctx : the pointer to C14N context object
2002-03-04 20:09:44 +03:00
* @ cur : the node to process
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Processes the given node
*
* Returns non - negative value on success or negative value on fail
*/
static int
2002-03-11 12:15:32 +03:00
xmlC14NProcessNode ( xmlC14NCtxPtr ctx , xmlNodePtr cur )
{
2002-03-04 20:09:44 +03:00
int ret = 0 ;
int visible ;
2002-03-11 12:15:32 +03:00
if ( ( ctx = = NULL ) | | ( cur = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-08-01 10:31:50 +04:00
visible = xmlC14NIsVisible ( ctx , cur , cur - > parent ) ;
2002-03-11 12:15:32 +03:00
switch ( cur - > type ) {
case XML_ELEMENT_NODE :
ret = xmlC14NProcessElementNode ( ctx , cur , visible ) ;
break ;
case XML_CDATA_SECTION_NODE :
case XML_TEXT_NODE :
/*
* Text Nodes
2012-09-11 09:26:36 +04:00
* the string value , except all ampersands are replaced
* by & amp ; , all open angle brackets ( < ) are replaced by & lt ; , all closing
* angle brackets ( > ) are replaced by & gt ; , and all # xD characters are
2002-03-11 12:15:32 +03:00
* replaced by & # xD ; .
*/
/* cdata sections are processed as text nodes */
/* todo: verify that cdata sections are included in XPath nodes set */
if ( ( visible ) & & ( cur - > content ! = NULL ) ) {
xmlChar * buffer ;
buffer = xmlC11NNormalizeText ( cur - > content ) ;
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) buffer ) ;
xmlFree ( buffer ) ;
} else {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
}
break ;
case XML_PI_NODE :
2012-09-11 09:26:36 +04:00
/*
* Processing Instruction ( PI ) Nodes -
* The opening PI symbol ( < ? ) , the PI target name of the node ,
* a leading space and the string value if it is not empty , and
* the closing PI symbol ( ? > ) . If the string value is empty ,
* then the leading space is not added . Also , a trailing # xA is
* rendered after the closing PI symbol for PI children of the
* root node with a lesser document order than the document
* element , and a leading # xA is rendered before the opening PI
* symbol of PI children of the root node with a greater document
2002-03-11 12:15:32 +03:00
* order than the document element .
*/
if ( visible ) {
if ( ctx - > pos = = XMLC14N_AFTER_DOCUMENT_ELEMENT ) {
xmlOutputBufferWriteString ( ctx - > buf , " \x0A <? " ) ;
} else {
xmlOutputBufferWriteString ( ctx - > buf , " <? " ) ;
}
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) cur - > name ) ;
if ( ( cur - > content ! = NULL ) & & ( * ( cur - > content ) ! = ' \0 ' ) ) {
xmlChar * buffer ;
xmlOutputBufferWriteString ( ctx - > buf , " " ) ;
/* todo: do we need to normalize pi? */
buffer = xmlC11NNormalizePI ( cur - > content ) ;
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) buffer ) ;
xmlFree ( buffer ) ;
} else {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
}
if ( ctx - > pos = = XMLC14N_BEFORE_DOCUMENT_ELEMENT ) {
xmlOutputBufferWriteString ( ctx - > buf , " ?> \x0A " ) ;
} else {
xmlOutputBufferWriteString ( ctx - > buf , " ?> " ) ;
}
}
break ;
case XML_COMMENT_NODE :
/*
* Comment Nodes
2012-09-11 09:26:36 +04:00
* Nothing if generating canonical XML without comments . For
* canonical XML with comments , generate the opening comment
* symbol ( < ! - - ) , the string value of the node , and the
* closing comment symbol ( - - > ) . Also , a trailing # xA is rendered
* after the closing comment symbol for comment children of the
* root node with a lesser document order than the document
* element , and a leading # xA is rendered before the opening
* comment symbol of comment children of the root node with a
* greater document order than the document element . ( Comment
* children of the root node represent comments outside of the
* top - level document element and outside of the document type
2002-03-11 12:15:32 +03:00
* declaration ) .
*/
if ( visible & & ctx - > with_comments ) {
if ( ctx - > pos = = XMLC14N_AFTER_DOCUMENT_ELEMENT ) {
xmlOutputBufferWriteString ( ctx - > buf , " \x0A <!-- " ) ;
} else {
xmlOutputBufferWriteString ( ctx - > buf , " <!-- " ) ;
}
if ( cur - > content ! = NULL ) {
xmlChar * buffer ;
/* todo: do we need to normalize comment? */
buffer = xmlC11NNormalizeComment ( cur - > content ) ;
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( ctx - > buf ,
( const char * ) buffer ) ;
xmlFree ( buffer ) ;
} else {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
}
}
if ( ctx - > pos = = XMLC14N_BEFORE_DOCUMENT_ELEMENT ) {
xmlOutputBufferWriteString ( ctx - > buf , " --> \x0A " ) ;
} else {
xmlOutputBufferWriteString ( ctx - > buf , " --> " ) ;
}
}
break ;
case XML_DOCUMENT_NODE :
case XML_DOCUMENT_FRAG_NODE : /* should be processed as document? */
2002-03-21 11:05:23 +03:00
# ifdef LIBXML_HTML_ENABLED
2002-03-11 12:15:32 +03:00
case XML_HTML_DOCUMENT_NODE : /* should be processed as document? */
2002-03-21 11:05:23 +03:00
# endif
2002-03-11 12:15:32 +03:00
if ( cur - > children ! = NULL ) {
ctx - > pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT ;
ctx - > parent_is_doc = 1 ;
ret = xmlC14NProcessNodeList ( ctx , cur - > children ) ;
}
break ;
case XML_ATTRIBUTE_NODE :
2023-12-18 22:58:42 +03:00
xmlC14NErrInvalidNode ( ctx , " XML_ATTRIBUTE_NODE " , " processing node " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
case XML_NAMESPACE_DECL :
2023-12-18 22:58:42 +03:00
xmlC14NErrInvalidNode ( ctx , " XML_NAMESPACE_DECL " , " processing node " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
case XML_ENTITY_REF_NODE :
2023-12-18 22:58:42 +03:00
xmlC14NErrInvalidNode ( ctx , " XML_ENTITY_REF_NODE " , " processing node " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
case XML_ENTITY_NODE :
2023-12-18 22:58:42 +03:00
xmlC14NErrInvalidNode ( ctx , " XML_ENTITY_NODE " , " processing node " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
case XML_DOCUMENT_TYPE_NODE :
case XML_NOTATION_NODE :
case XML_DTD_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
2002-03-21 11:05:23 +03:00
# ifdef LIBXML_XINCLUDE_ENABLED
2002-03-11 12:15:32 +03:00
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2002-03-21 11:05:23 +03:00
# endif
2012-09-11 09:26:36 +04:00
/*
* should be ignored according to " W3C Canonical XML "
2002-03-11 12:15:32 +03:00
*/
break ;
default :
2023-12-18 22:58:42 +03:00
xmlC14NErrUnknownNode ( ctx , cur - > type , " processing node " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
return ( ret ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NProcessNodeList :
2012-09-11 09:26:36 +04:00
* @ ctx : the pointer to C14N context object
2002-03-04 20:09:44 +03:00
* @ cur : the node to start from
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Processes all nodes in the row starting from cur .
*
* Returns non - negative value on success or negative value on fail
*/
static int
2002-03-11 12:15:32 +03:00
xmlC14NProcessNodeList ( xmlC14NCtxPtr ctx , xmlNodePtr cur )
{
2002-03-04 20:09:44 +03:00
int ret ;
2002-03-11 12:15:32 +03:00
if ( ctx = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
for ( ret = 0 ; cur ! = NULL & & ret > = 0 ; cur = cur - > next ) {
ret = xmlC14NProcessNode ( ctx , cur ) ;
}
return ( ret ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NFreeCtx :
* @ ctx : the pointer to C14N context object
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Cleanups the C14N context object .
*/
static void
2002-03-11 12:15:32 +03:00
xmlC14NFreeCtx ( xmlC14NCtxPtr ctx )
{
if ( ctx = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
if ( ctx - > ns_rendered ! = NULL ) {
2002-06-04 08:27:06 +04:00
xmlC14NVisibleNsStackDestroy ( ctx - > ns_rendered ) ;
2002-03-04 20:09:44 +03:00
}
xmlFree ( ctx ) ;
}
/**
* xmlC14NNewCtx :
2012-09-11 09:26:36 +04:00
* @ doc : the XML document for canonization
* @ is_visible_callback : the function to use to determine is node visible
2002-08-01 10:31:50 +04:00
* or not
2012-09-11 09:26:36 +04:00
* @ user_data : the first parameter for @ is_visible_callback function
2002-08-01 10:31:50 +04:00
* ( in most cases , it is nodes set )
2009-07-09 12:26:22 +04:00
* @ mode : the c14n mode ( see @ xmlC14NMode )
2012-09-11 09:26:36 +04:00
* @ inclusive_ns_prefixe the list of inclusive namespace prefixes
2002-03-04 20:09:44 +03:00
* ended with a NULL or NULL if there is no
2012-09-11 09:26:36 +04:00
* inclusive namespaces ( only for `
2002-03-04 20:09:44 +03:00
* canonicalization )
2012-09-11 09:26:36 +04:00
* @ with_comments : include comments in the result ( ! = 0 ) or not ( = = 0 )
* @ buf : the output buffer to store canonical XML ; this
2002-03-04 20:09:44 +03:00
* buffer MUST have encoder = = NULL because C14N requires
* UTF - 8 output
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Creates new C14N context object to store C14N parameters .
*
* Returns pointer to newly created object ( success ) or NULL ( fail )
*/
static xmlC14NCtxPtr
2012-09-11 09:26:36 +04:00
xmlC14NNewCtx ( xmlDocPtr doc ,
2002-08-01 10:31:50 +04:00
xmlC14NIsVisibleCallback is_visible_callback , void * user_data ,
2009-07-09 12:26:22 +04:00
xmlC14NMode mode , xmlChar * * inclusive_ns_prefixes ,
2002-03-11 12:15:32 +03:00
int with_comments , xmlOutputBufferPtr buf )
{
2003-10-10 18:10:40 +04:00
xmlC14NCtxPtr ctx = NULL ;
2002-03-04 20:09:44 +03:00
2002-03-11 12:15:32 +03:00
if ( ( doc = = NULL ) | | ( buf = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( NULL ) ;
2002-03-04 20:09:44 +03:00
}
/*
* Validate the encoding output buffer encoding
*/
2002-03-11 12:15:32 +03:00
if ( buf - > encoder ! = NULL ) {
2003-10-10 16:30:37 +04:00
xmlC14NErr ( ctx , ( xmlNodePtr ) doc , XML_C14N_REQUIRES_UTF8 ,
" xmlC14NNewCtx: output buffer encoder != NULL but C14N requires UTF8 output \n " ) ;
2002-03-11 12:15:32 +03:00
return ( NULL ) ;
2002-03-04 20:09:44 +03:00
}
/*
* Allocate a new xmlC14NCtxPtr and fill the fields .
*/
ctx = ( xmlC14NCtxPtr ) xmlMalloc ( sizeof ( xmlC14NCtx ) ) ;
if ( ctx = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-03-11 12:15:32 +03:00
return ( NULL ) ;
2002-03-04 20:09:44 +03:00
}
memset ( ctx , 0 , sizeof ( xmlC14NCtx ) ) ;
/*
* initialize C14N context
2002-03-11 12:15:32 +03:00
*/
2002-03-04 20:09:44 +03:00
ctx - > doc = doc ;
ctx - > with_comments = with_comments ;
2002-08-01 10:31:50 +04:00
ctx - > is_visible_callback = is_visible_callback ;
ctx - > user_data = user_data ;
2002-03-04 20:09:44 +03:00
ctx - > buf = buf ;
ctx - > parent_is_doc = 1 ;
ctx - > pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT ;
2002-06-04 08:27:06 +04:00
ctx - > ns_rendered = xmlC14NVisibleNsStackCreate ( ) ;
if ( ctx - > ns_rendered = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( ctx ) ;
2002-06-04 08:27:06 +04:00
xmlC14NFreeCtx ( ctx ) ;
return ( NULL ) ;
}
2002-03-04 20:09:44 +03:00
/*
2019-09-30 18:04:54 +03:00
* Set " mode " flag and remember list of inclusive prefixes
2009-07-09 12:26:22 +04:00
* for exclusive c14n
2002-03-04 20:09:44 +03:00
*/
2009-07-09 12:26:22 +04:00
ctx - > mode = mode ;
if ( xmlC14NIsExclusive ( ctx ) ) {
2002-03-04 20:09:44 +03:00
ctx - > inclusive_ns_prefixes = inclusive_ns_prefixes ;
}
2023-12-18 22:58:42 +03:00
2002-03-11 12:15:32 +03:00
return ( ctx ) ;
2002-03-04 20:09:44 +03:00
}
/**
2002-08-01 10:31:50 +04:00
* xmlC14NExecute :
2012-09-11 09:26:36 +04:00
* @ doc : the XML document for canonization
* @ is_visible_callback : the function to use to determine is node visible
2002-08-01 10:31:50 +04:00
* or not
2012-09-11 09:26:36 +04:00
* @ user_data : the first parameter for @ is_visible_callback function
2002-08-01 10:31:50 +04:00
* ( in most cases , it is nodes set )
2009-07-09 12:26:22 +04:00
* @ mode : the c14n mode ( see @ xmlC14NMode )
2012-09-11 09:26:36 +04:00
* @ inclusive_ns_prefixes : the list of inclusive namespace prefixes
2002-03-04 20:09:44 +03:00
* ended with a NULL or NULL if there is no
2012-09-11 09:26:36 +04:00
* inclusive namespaces ( only for exclusive
2002-03-04 20:09:44 +03:00
* canonicalization , ignored otherwise )
2012-09-11 09:26:36 +04:00
* @ with_comments : include comments in the result ( ! = 0 ) or not ( = = 0 )
* @ buf : the output buffer to store canonical XML ; this
2002-03-04 20:09:44 +03:00
* buffer MUST have encoder = = NULL because C14N requires
* UTF - 8 output
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Dumps the canonized image of given XML document into the provided buffer .
* For details see " Canonical XML " ( http : //www.w3.org/TR/xml-c14n) or
* " Exclusive XML Canonicalization " ( http : //www.w3.org/TR/xml-exc-c14n)
*
2012-09-11 09:26:36 +04:00
* Returns non - negative value on success or a negative value on fail
2002-03-04 20:09:44 +03:00
*/
2012-09-11 09:26:36 +04:00
int
2002-08-01 10:31:50 +04:00
xmlC14NExecute ( xmlDocPtr doc , xmlC14NIsVisibleCallback is_visible_callback ,
2009-07-10 00:54:00 +04:00
void * user_data , int mode , xmlChar * * inclusive_ns_prefixes ,
2002-08-01 10:31:50 +04:00
int with_comments , xmlOutputBufferPtr buf ) {
2002-03-04 20:09:44 +03:00
xmlC14NCtxPtr ctx ;
2009-07-10 00:54:00 +04:00
xmlC14NMode c14n_mode = XML_C14N_1_0 ;
2002-03-04 20:09:44 +03:00
int ret ;
2002-03-11 12:15:32 +03:00
if ( ( buf = = NULL ) | | ( doc = = NULL ) ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/* for backward compatibility, we have to have "mode" as "int"
2009-07-10 00:54:00 +04:00
and here we check that user gives valid value */
switch ( mode ) {
case XML_C14N_1_0 :
case XML_C14N_EXCLUSIVE_1_0 :
2012-09-11 09:26:36 +04:00
case XML_C14N_1_1 :
2009-07-10 00:54:00 +04:00
c14n_mode = ( xmlC14NMode ) mode ;
break ;
2012-09-11 09:26:36 +04:00
default :
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2009-07-10 00:54:00 +04:00
return ( - 1 ) ;
}
2002-03-04 20:09:44 +03:00
/*
* Validate the encoding output buffer encoding
*/
2002-03-11 12:15:32 +03:00
if ( buf - > encoder ! = NULL ) {
2003-10-10 16:30:37 +04:00
xmlC14NErr ( NULL , ( xmlNodePtr ) doc , XML_C14N_REQUIRES_UTF8 ,
" xmlC14NExecute: output buffer encoder != NULL but C14N requires UTF8 output \n " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
ctx = xmlC14NNewCtx ( doc , is_visible_callback , user_data ,
2009-07-10 00:54:00 +04:00
c14n_mode , inclusive_ns_prefixes ,
with_comments , buf ) ;
2002-03-11 12:15:32 +03:00
if ( ctx = = NULL ) {
2003-10-10 16:30:37 +04:00
xmlC14NErr ( NULL , ( xmlNodePtr ) doc , XML_C14N_CREATE_CTXT ,
" xmlC14NExecute: unable to create C14N context \n " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Root Node
2012-09-11 09:26:36 +04:00
* The root node is the parent of the top - level document element . The
* result of processing each of its child nodes that is in the node - set
* in document order . The root node does not generate a byte order mark ,
* XML declaration , nor anything from within the document type
2002-03-04 20:09:44 +03:00
* declaration .
*/
2002-03-11 12:15:32 +03:00
if ( doc - > children ! = NULL ) {
ret = xmlC14NProcessNodeList ( ctx , doc - > children ) ;
if ( ret < 0 ) {
xmlC14NFreeCtx ( ctx ) ;
return ( - 1 ) ;
}
}
2002-03-04 20:09:44 +03:00
/*
* Flush buffer to get number of bytes written
*/
ret = xmlOutputBufferFlush ( buf ) ;
2002-03-11 12:15:32 +03:00
if ( ret < 0 ) {
2024-02-04 16:08:44 +03:00
xmlC14NErr ( ctx , NULL , buf - > error , " flushing output buffer " ) ;
2002-03-11 12:15:32 +03:00
xmlC14NFreeCtx ( ctx ) ;
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* Cleanup
*/
2002-03-11 12:15:32 +03:00
xmlC14NFreeCtx ( ctx ) ;
return ( ret ) ;
2002-03-04 20:09:44 +03:00
}
2002-08-01 10:31:50 +04:00
/**
* xmlC14NDocSaveTo :
2012-09-11 09:26:36 +04:00
* @ doc : the XML document for canonization
* @ nodes : the nodes set to be included in the canonized image
* or NULL if all document nodes should be included
2009-07-09 12:26:22 +04:00
* @ mode : the c14n mode ( see @ xmlC14NMode )
2012-09-11 09:26:36 +04:00
* @ inclusive_ns_prefixes : the list of inclusive namespace prefixes
2002-08-01 10:31:50 +04:00
* ended with a NULL or NULL if there is no
2012-09-11 09:26:36 +04:00
* inclusive namespaces ( only for exclusive
2002-08-01 10:31:50 +04:00
* canonicalization , ignored otherwise )
2012-09-11 09:26:36 +04:00
* @ with_comments : include comments in the result ( ! = 0 ) or not ( = = 0 )
* @ buf : the output buffer to store canonical XML ; this
2002-08-01 10:31:50 +04:00
* buffer MUST have encoder = = NULL because C14N requires
* UTF - 8 output
2012-09-11 09:26:36 +04:00
*
2002-08-01 10:31:50 +04:00
* Dumps the canonized image of given XML document into the provided buffer .
* For details see " Canonical XML " ( http : //www.w3.org/TR/xml-c14n) or
* " Exclusive XML Canonicalization " ( http : //www.w3.org/TR/xml-exc-c14n)
*
2012-09-11 09:26:36 +04:00
* Returns non - negative value on success or a negative value on fail
2002-08-01 10:31:50 +04:00
*/
int
xmlC14NDocSaveTo ( xmlDocPtr doc , xmlNodeSetPtr nodes ,
2009-07-09 12:26:22 +04:00
int mode , xmlChar * * inclusive_ns_prefixes ,
2002-08-01 10:31:50 +04:00
int with_comments , xmlOutputBufferPtr buf ) {
2012-09-11 09:26:36 +04:00
return ( xmlC14NExecute ( doc ,
2017-11-09 19:29:22 +03:00
xmlC14NIsNodeInNodeset ,
2002-08-01 10:31:50 +04:00
nodes ,
2009-07-09 12:26:22 +04:00
mode ,
2002-08-01 10:31:50 +04:00
inclusive_ns_prefixes ,
with_comments ,
buf ) ) ;
}
2002-03-04 20:09:44 +03:00
/**
* xmlC14NDocDumpMemory :
2012-09-11 09:26:36 +04:00
* @ doc : the XML document for canonization
* @ nodes : the nodes set to be included in the canonized image
* or NULL if all document nodes should be included
2009-07-09 12:26:22 +04:00
* @ mode : the c14n mode ( see @ xmlC14NMode )
2012-09-11 09:26:36 +04:00
* @ inclusive_ns_prefixes : the list of inclusive namespace prefixes
2002-03-04 20:09:44 +03:00
* ended with a NULL or NULL if there is no
2012-09-11 09:26:36 +04:00
* inclusive namespaces ( only for exclusive
2002-03-04 20:09:44 +03:00
* canonicalization , ignored otherwise )
2012-09-11 09:26:36 +04:00
* @ with_comments : include comments in the result ( ! = 0 ) or not ( = = 0 )
* @ doc_txt_ptr : the memory pointer for allocated canonical XML text ;
2002-03-04 20:09:44 +03:00
* the caller of this functions is responsible for calling
2012-09-11 09:26:36 +04:00
* xmlFree ( ) to free allocated memory
*
2002-03-04 20:09:44 +03:00
* Dumps the canonized image of given XML document into memory .
* For details see " Canonical XML " ( http : //www.w3.org/TR/xml-c14n) or
* " Exclusive XML Canonicalization " ( http : //www.w3.org/TR/xml-exc-c14n)
*
2012-09-11 09:26:36 +04:00
* Returns the number of bytes written on success or a negative value on fail
2002-03-04 20:09:44 +03:00
*/
int
2002-03-11 12:15:32 +03:00
xmlC14NDocDumpMemory ( xmlDocPtr doc , xmlNodeSetPtr nodes ,
2009-07-10 00:54:00 +04:00
int mode , xmlChar * * inclusive_ns_prefixes ,
2002-03-11 12:15:32 +03:00
int with_comments , xmlChar * * doc_txt_ptr )
{
2002-03-04 20:09:44 +03:00
int ret ;
xmlOutputBufferPtr buf ;
if ( doc_txt_ptr = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
* doc_txt_ptr = NULL ;
2002-03-11 12:15:32 +03:00
2002-03-04 20:09:44 +03:00
/*
2012-09-11 09:26:36 +04:00
* create memory buffer with UTF8 ( default ) encoding
2002-03-04 20:09:44 +03:00
*/
buf = xmlAllocOutputBuffer ( NULL ) ;
2002-03-11 12:15:32 +03:00
if ( buf = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( NULL ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
/*
* canonize document and write to buffer
*/
2009-07-09 12:26:22 +04:00
ret = xmlC14NDocSaveTo ( doc , nodes , mode , inclusive_ns_prefixes ,
2002-03-11 12:15:32 +03:00
with_comments , buf ) ;
if ( ret < 0 ) {
( void ) xmlOutputBufferClose ( buf ) ;
return ( - 1 ) ;
}
2012-07-16 10:37:00 +04:00
ret = xmlBufUse ( buf - > buffer ) ;
2020-06-24 21:07:32 +03:00
if ( ret > = 0 ) {
2012-07-16 10:37:00 +04:00
* doc_txt_ptr = xmlStrndup ( xmlBufContent ( buf - > buffer ) , ret ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
( void ) xmlOutputBufferClose ( buf ) ;
2002-03-04 20:09:44 +03:00
2020-06-24 21:07:32 +03:00
if ( ( * doc_txt_ptr = = NULL ) & & ( ret > = 0 ) ) {
2024-02-04 16:08:44 +03:00
xmlC14NErrMemory ( NULL ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
return ( ret ) ;
2002-03-04 20:09:44 +03:00
}
/**
* xmlC14NDocSave :
2012-09-11 09:26:36 +04:00
* @ doc : the XML document for canonization
* @ nodes : the nodes set to be included in the canonized image
* or NULL if all document nodes should be included
2009-07-09 12:26:22 +04:00
* @ mode : the c14n mode ( see @ xmlC14NMode )
2012-09-11 09:26:36 +04:00
* @ inclusive_ns_prefixes : the list of inclusive namespace prefixes
2002-03-04 20:09:44 +03:00
* ended with a NULL or NULL if there is no
2012-09-11 09:26:36 +04:00
* inclusive namespaces ( only for exclusive
2002-03-04 20:09:44 +03:00
* canonicalization , ignored otherwise )
2012-09-11 09:26:36 +04:00
* @ with_comments : include comments in the result ( ! = 0 ) or not ( = = 0 )
* @ filename : the filename to store canonical XML image
2019-09-30 18:04:54 +03:00
* @ compression : the compression level ( zlib required ) :
2002-03-04 20:09:44 +03:00
* - 1 - libxml default ,
2012-09-11 09:26:36 +04:00
* 0 - uncompressed ,
2002-03-04 20:09:44 +03:00
* > 0 - compression level
2012-09-11 09:26:36 +04:00
*
2002-03-04 20:09:44 +03:00
* Dumps the canonized image of given XML document into the file .
* For details see " Canonical XML " ( http : //www.w3.org/TR/xml-c14n) or
* " Exclusive XML Canonicalization " ( http : //www.w3.org/TR/xml-exc-c14n)
*
2012-09-11 09:26:36 +04:00
* Returns the number of bytes written success or a negative value on fail
2002-03-04 20:09:44 +03:00
*/
int
2002-03-11 12:15:32 +03:00
xmlC14NDocSave ( xmlDocPtr doc , xmlNodeSetPtr nodes ,
2009-07-10 00:54:00 +04:00
int mode , xmlChar * * inclusive_ns_prefixes ,
2002-03-11 12:15:32 +03:00
int with_comments , const char * filename , int compression )
{
xmlOutputBufferPtr buf ;
2002-03-04 20:09:44 +03:00
int ret ;
2002-03-11 12:15:32 +03:00
if ( filename = = NULL ) {
2023-12-18 22:58:42 +03:00
xmlC14NErrParam ( NULL ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2017-11-13 19:08:38 +03:00
# ifdef LIBXML_ZLIB_ENABLED
2002-03-11 12:15:32 +03:00
if ( compression < 0 )
compression = xmlGetCompressMode ( ) ;
# endif
2002-03-04 20:09:44 +03:00
2012-09-11 09:26:36 +04:00
/*
2002-03-04 20:09:44 +03:00
* save the content to a temp buffer , use default UTF8 encoding .
*/
buf = xmlOutputBufferCreateFilename ( filename , NULL , compression ) ;
if ( buf = = NULL ) {
2024-02-04 16:08:44 +03:00
xmlC14NErr ( NULL , NULL , XML_IO_UNKNOWN , " creating temporary filename " ) ;
2002-03-11 12:15:32 +03:00
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
2002-03-04 20:09:44 +03:00
/*
* canonize document and write to buffer
*/
2009-07-09 12:26:22 +04:00
ret = xmlC14NDocSaveTo ( doc , nodes , mode , inclusive_ns_prefixes ,
2002-03-11 12:15:32 +03:00
with_comments , buf ) ;
if ( ret < 0 ) {
( void ) xmlOutputBufferClose ( buf ) ;
return ( - 1 ) ;
2002-03-04 20:09:44 +03:00
}
2002-03-11 12:15:32 +03:00
2012-09-11 09:26:36 +04:00
/*
* get the numbers of bytes written
2002-03-04 20:09:44 +03:00
*/
ret = xmlOutputBufferClose ( buf ) ;
2002-03-11 12:15:32 +03:00
return ( ret ) ;
2002-03-04 20:09:44 +03:00
}
2012-09-11 09:26:36 +04:00
/**
2002-03-04 20:09:44 +03:00
* xmlC11NNormalizeString :
* @ input : the input string
* @ mode : the normalization mode ( attribute , comment , PI or text )
*
* Converts a string to a canonical ( normalized ) format . The code is stolen
* from xmlEncodeEntitiesReentrant ( ) . Added normalization of \ x09 , \ x0a , \ x0A
* and the @ mode parameter
*
* Returns a normalized string ( caller is responsible for calling xmlFree ( ) )
* or NULL if an error occurs
*/
static xmlChar *
2002-03-11 12:15:32 +03:00
xmlC11NNormalizeString ( const xmlChar * input ,
xmlC14NNormalizationMode mode )
{
2002-03-04 20:09:44 +03:00
const xmlChar * cur = input ;
xmlChar * buffer = NULL ;
xmlChar * out = NULL ;
int buffer_size = 0 ;
2002-03-11 12:15:32 +03:00
if ( input = = NULL )
return ( NULL ) ;
2002-03-04 20:09:44 +03:00
/*
* allocate an translation buffer .
*/
buffer_size = 1000 ;
2022-09-01 04:14:13 +03:00
buffer = ( xmlChar * ) xmlMallocAtomic ( buffer_size ) ;
2024-02-04 16:08:44 +03:00
if ( buffer = = NULL )
2002-03-11 12:15:32 +03:00
return ( NULL ) ;
2002-03-04 20:09:44 +03:00
out = buffer ;
while ( * cur ! = ' \0 ' ) {
2002-03-11 12:15:32 +03:00
if ( ( out - buffer ) > ( buffer_size - 10 ) ) {
2024-05-07 13:15:24 +03:00
xmlChar * tmp ;
2002-03-11 12:15:32 +03:00
int indx = out - buffer ;
2024-05-07 13:15:24 +03:00
buffer_size * = 2 ;
tmp = xmlRealloc ( buffer , buffer_size ) ;
if ( tmp = = NULL ) {
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buffer = tmp ;
2002-03-11 12:15:32 +03:00
out = & buffer [ indx ] ;
}
if ( ( * cur = = ' < ' ) & & ( ( mode = = XMLC14N_NORMALIZE_ATTR ) | |
( mode = = XMLC14N_NORMALIZE_TEXT ) ) ) {
* out + + = ' & ' ;
* out + + = ' l ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( ( * cur = = ' > ' ) & & ( mode = = XMLC14N_NORMALIZE_TEXT ) ) {
* out + + = ' & ' ;
* out + + = ' g ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( ( * cur = = ' & ' ) & & ( ( mode = = XMLC14N_NORMALIZE_ATTR ) | |
( mode = = XMLC14N_NORMALIZE_TEXT ) ) ) {
* out + + = ' & ' ;
* out + + = ' a ' ;
* out + + = ' m ' ;
* out + + = ' p ' ;
* out + + = ' ; ' ;
} else if ( ( * cur = = ' " ' ) & & ( mode = = XMLC14N_NORMALIZE_ATTR ) ) {
* out + + = ' & ' ;
* out + + = ' q ' ;
* out + + = ' u ' ;
* out + + = ' o ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( ( * cur = = ' \x09 ' ) & & ( mode = = XMLC14N_NORMALIZE_ATTR ) ) {
* out + + = ' & ' ;
* out + + = ' # ' ;
* out + + = ' x ' ;
* out + + = ' 9 ' ;
* out + + = ' ; ' ;
} else if ( ( * cur = = ' \x0A ' ) & & ( mode = = XMLC14N_NORMALIZE_ATTR ) ) {
* out + + = ' & ' ;
* out + + = ' # ' ;
* out + + = ' x ' ;
* out + + = ' A ' ;
* out + + = ' ; ' ;
} else if ( ( * cur = = ' \x0D ' ) & & ( ( mode = = XMLC14N_NORMALIZE_ATTR ) | |
( mode = = XMLC14N_NORMALIZE_TEXT ) | |
( mode = = XMLC14N_NORMALIZE_COMMENT ) | |
( mode = = XMLC14N_NORMALIZE_PI ) ) ) {
* out + + = ' & ' ;
* out + + = ' # ' ;
* out + + = ' x ' ;
* out + + = ' D ' ;
* out + + = ' ; ' ;
} else {
/*
* Works because on UTF - 8 , all extended sequences cannot
* result in bytes in the ASCII range .
*/
* out + + = * cur ;
}
cur + + ;
2002-03-04 20:09:44 +03:00
}
2009-09-05 16:52:55 +04:00
* out = 0 ;
2002-03-11 12:15:32 +03:00
return ( buffer ) ;
2002-03-04 20:09:44 +03:00
}
2022-02-20 20:46:42 +03:00
2002-03-04 20:09:44 +03:00
# endif /* LIBXML_C14N_ENABLED */