xmlsecurityengine/xmlsec/src/xmlsec_nodeset.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * Enchanced nodes set
       
     5  *
       
     6  * This is free software; see Copyright file in the source
       
     7  * distribution for preciese wording.
       
     8  * 
       
     9  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    10  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    11  */
       
    12 #include "xmlsec_globals.h"
       
    13 
       
    14 #include <stdlib.h>
       
    15 #include <string.h>
       
    16  
       
    17 #include <libxml2_tree.h>
       
    18 #include <libxml2_xpath.h>
       
    19 #include <libxml2_xpathinternals.h>
       
    20 #include <libxml2_globals.h>
       
    21 
       
    22 #include "xmlsec_xmlsec.h"
       
    23 #include "xmlsec_nodeset.h"
       
    24 #include "xmlsec_errors.h"
       
    25 
       
    26 #define xmlSecGetParent(node)           \
       
    27     (((node)->type != XML_NAMESPACE_DECL) ? \
       
    28         (node)->parent : \
       
    29         (xmlNodePtr)((xmlNsPtr)(node))->next)
       
    30 	
       
    31 static int	xmlSecNodeSetOneContains		(xmlSecNodeSetPtr nset, 
       
    32 							 xmlNodePtr node, 
       
    33 							 xmlNodePtr parent);
       
    34 static int	xmlSecNodeSetWalkRecursive		(xmlSecNodeSetPtr nset, 
       
    35 							 xmlSecNodeSetWalkCallback walkFunc, 
       
    36 							 void* data, 
       
    37 							 xmlNodePtr cur, 
       
    38 							 xmlNodePtr parent);
       
    39 
       
    40 /**
       
    41  * xmlSecNodeSetCreate:
       
    42  * @doc: 		the pointer to parent XML document.
       
    43  * @nodes: 		the list of nodes.
       
    44  * @type: 		the nodes set type.
       
    45  *
       
    46  * Creates new nodes set. Caller is responsible for freeng returend object
       
    47  * by calling #xmlSecNodeSetDestroy function.
       
    48  *
       
    49  * Returns pointer to newly allocated node set or NULL if an error occurs.
       
    50  */
       
    51 EXPORT_C
       
    52 xmlSecNodeSetPtr
       
    53 xmlSecNodeSetCreate(xmlDocPtr doc, xmlNodeSetPtr nodes, xmlSecNodeSetType type) {
       
    54     xmlSecNodeSetPtr nset;
       
    55 
       
    56     nset = (xmlSecNodeSetPtr)xmlMalloc(sizeof(xmlSecNodeSet));
       
    57     if(nset == NULL) { 
       
    58 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    59 		    NULL,
       
    60 		    NULL,
       
    61 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
    62 		    "sizeof(xmlSecNodeSet)=%d",
       
    63 		    sizeof(xmlSecNodeSet));
       
    64 	return(NULL);
       
    65     }
       
    66     memset(nset, 0,  sizeof(xmlSecNodeSet));
       
    67     
       
    68     nset->doc 	= doc;
       
    69     nset->nodes = nodes;
       
    70     nset->type	= type;
       
    71     nset->next 	= nset->prev = nset;
       
    72     return(nset);
       
    73 }
       
    74 
       
    75 /**
       
    76  * xmlSecNodeSetDestroy:
       
    77  * @nset: 		the pointer to node set.
       
    78  *
       
    79  * Destroys the nodes set created with #xmlSecNodeSetCreate function.
       
    80  */
       
    81 EXPORT_C
       
    82 void
       
    83 xmlSecNodeSetDestroy(xmlSecNodeSetPtr nset) {
       
    84     xmlSecNodeSetPtr tmp;
       
    85 
       
    86     xmlSecAssert(nset != NULL);
       
    87     	
       
    88     while((tmp = nset) != NULL) {
       
    89 	if((nset->next != NULL) && (nset->next != nset)) {
       
    90 	    nset->next->prev = nset->prev;
       
    91 	    nset->prev->next = nset->next;	    
       
    92 	    nset = nset->next;
       
    93 	} else {
       
    94 	    nset = NULL;
       
    95 	}
       
    96 	
       
    97 	if(tmp->nodes != NULL) {
       
    98     	    xmlXPathFreeNodeSet(tmp->nodes);
       
    99 	}
       
   100 	if(tmp->children != NULL) {
       
   101 	    xmlSecNodeSetDestroy(tmp->children);
       
   102 	}
       
   103 	if((tmp->doc != NULL) && (tmp->destroyDoc != 0)) {
       
   104 	    xmlFreeDoc(tmp->doc);
       
   105 	}
       
   106 	memset(tmp, 0,  sizeof(xmlSecNodeSet));
       
   107         xmlFree(tmp);
       
   108     }
       
   109 }
       
   110 
       
   111 /**
       
   112  * xmlSecNodeSetDocDestroy:
       
   113  * @nset: 		the pointer to node set.
       
   114  *
       
   115  * Instructs node set to destroy nodes parent doc when node set is destroyed.
       
   116  */
       
   117 EXPORT_C
       
   118 void 
       
   119 xmlSecNodeSetDocDestroy(xmlSecNodeSetPtr nset) {
       
   120     xmlSecAssert(nset != NULL);
       
   121     
       
   122     nset->destroyDoc = 1;
       
   123 }
       
   124 
       
   125 static int
       
   126 xmlSecNodeSetOneContains(xmlSecNodeSetPtr nset, xmlNodePtr node, xmlNodePtr parent) {
       
   127     int in_nodes_set = 1;
       
   128     
       
   129     xmlSecAssert2(nset != NULL, 0);
       
   130     xmlSecAssert2(node != NULL, 0);
       
   131         
       
   132     /* special cases: */
       
   133     switch(nset->type) {
       
   134 	case xmlSecNodeSetTreeWithoutComments:
       
   135         case xmlSecNodeSetTreeWithoutCommentsInvert:
       
   136 	    if(node->type == XML_COMMENT_NODE) {
       
   137 		return(0);
       
   138 	    }
       
   139 	    break;
       
   140 	case xmlSecNodeSetList:
       
   141 	    return(xmlSecNodeSetContains(nset->children, node, parent));
       
   142 	default:
       
   143 	    break;
       
   144     }
       
   145         
       
   146     if(nset->nodes != NULL) {
       
   147 	if(node->type != XML_NAMESPACE_DECL) {
       
   148 	    in_nodes_set = xmlXPathNodeSetContains(nset->nodes, node);
       
   149 	} else {
       
   150 	    xmlNs ns;
       
   151 	    
       
   152 	    memcpy(&ns, node, sizeof(ns)); 
       
   153 	    
       
   154 	    if((parent != NULL) && (parent->type == XML_ATTRIBUTE_NODE)) {
       
   155 		ns.next = (xmlNsPtr)parent->parent;
       
   156 	    } else {
       
   157 		ns.next = (xmlNsPtr)parent; 
       
   158 	    }
       
   159 
       
   160 	    /* 
       
   161 	     * If the input is an XPath node-set, then the node-set must explicitly 
       
   162 	     * contain every node to be rendered to the canonical form.
       
   163 	     */
       
   164 	    in_nodes_set = (xmlXPathNodeSetContains(nset->nodes, (xmlNodePtr)&ns));
       
   165 	}
       
   166     }
       
   167     
       
   168     switch(nset->type) {
       
   169     case xmlSecNodeSetNormal:
       
   170 	return(in_nodes_set);
       
   171     case xmlSecNodeSetInvert:
       
   172 	return(!in_nodes_set);
       
   173     case xmlSecNodeSetTree:
       
   174     case xmlSecNodeSetTreeWithoutComments:
       
   175 	if(in_nodes_set) {
       
   176 	    return(1);
       
   177 	}
       
   178 	if((parent != NULL) && (parent->type == XML_ELEMENT_NODE)) {
       
   179 	    return(xmlSecNodeSetOneContains(nset, parent, parent->parent));
       
   180 	}
       
   181 	return(0);
       
   182     case xmlSecNodeSetTreeInvert:
       
   183     case xmlSecNodeSetTreeWithoutCommentsInvert:
       
   184 	if(in_nodes_set) {
       
   185 	    return(0);
       
   186 	}
       
   187 	if((parent != NULL) && (parent->type == XML_ELEMENT_NODE)) {
       
   188 	    return(xmlSecNodeSetOneContains(nset, parent, parent->parent));
       
   189 	}
       
   190 	return(1);
       
   191     default:
       
   192 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   193 		    NULL,
       
   194 		    NULL,
       
   195 		    XMLSEC_ERRORS_R_INVALID_TYPE,
       
   196 		    "type=%d", nset->type);
       
   197     }
       
   198     
       
   199     return(0);
       
   200 }
       
   201 
       
   202 /**
       
   203  * xmlSecNodeSetContains:
       
   204  * @nset: 		the pointer to node set.
       
   205  * @node: 		the pointer to XML node to check.
       
   206  * @parent: 		the pointer to @node parent node.
       
   207  *
       
   208  * Checks whether the @node is in the nodes set or not.
       
   209  *
       
   210  * Returns 1 if the @node is in the nodes set @nset, 0 if it is not
       
   211  * and a negative value if an error occurs.
       
   212  */
       
   213 EXPORT_C
       
   214 int
       
   215 xmlSecNodeSetContains(xmlSecNodeSetPtr nset, xmlNodePtr node, xmlNodePtr parent) {
       
   216     int status = 1;
       
   217     xmlSecNodeSetPtr cur;
       
   218     
       
   219     xmlSecAssert2(node != NULL, 0);
       
   220     
       
   221     /* special cases: */
       
   222     if(nset == NULL) {
       
   223 	return(1);
       
   224     }
       
   225     
       
   226     status = 1;
       
   227     cur = nset;
       
   228     do {
       
   229 	switch(cur->op) {
       
   230 	case xmlSecNodeSetIntersection:
       
   231 	    if(status && !xmlSecNodeSetOneContains(cur, node, parent)) {
       
   232 		status = 0;
       
   233 	    }
       
   234     	    break;
       
   235 	case xmlSecNodeSetSubtraction:
       
   236 	    if(status && xmlSecNodeSetOneContains(cur, node, parent)) {
       
   237 		status = 0;
       
   238 	    }
       
   239 	    break;
       
   240 	case xmlSecNodeSetUnion:
       
   241 	    if(!status && xmlSecNodeSetOneContains(cur, node, parent)) {
       
   242 		status = 1;
       
   243 	    }	
       
   244 	    break;
       
   245 	default:
       
   246 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   247 			NULL,
       
   248 			NULL,
       
   249 			XMLSEC_ERRORS_R_INVALID_OPERATION,
       
   250 			"operation=%d", cur->op);
       
   251 	    return(-1);
       
   252 	}
       
   253 	cur = cur->next;
       
   254     } while(cur != nset);
       
   255     
       
   256     return(status);
       
   257 }
       
   258 
       
   259 /**
       
   260  * xmlSecNodeSetAdd:
       
   261  * @nset: 		the pointer to currrent nodes set (or NULL).
       
   262  * @newNSet: 		the pointer to new nodes set.
       
   263  * @op: 		the operation type.
       
   264  *
       
   265  * Adds @newNSet to the @nset using operation @op. 
       
   266  *
       
   267  * Returns the pointer to combined nodes set or NULL if an error 
       
   268  * occurs.
       
   269  */
       
   270 EXPORT_C
       
   271 xmlSecNodeSetPtr	
       
   272 xmlSecNodeSetAdd(xmlSecNodeSetPtr nset, xmlSecNodeSetPtr newNSet, 
       
   273 		 xmlSecNodeSetOp op) {
       
   274     xmlSecAssert2(newNSet != NULL, NULL);
       
   275     xmlSecAssert2(newNSet->next == newNSet, NULL);
       
   276 
       
   277     newNSet->op	= op;
       
   278     if(nset == NULL) {
       
   279 	return(newNSet);
       
   280     }
       
   281         
       
   282     newNSet->next = nset;
       
   283     newNSet->prev = nset->prev;
       
   284     nset->prev->next = newNSet;
       
   285     nset->prev 	     = newNSet;
       
   286     return(nset);
       
   287 }
       
   288 
       
   289 /**
       
   290  * xmlSecNodeSetAddList:
       
   291  * @nset: 		the pointer to currrent nodes set (or NULL).
       
   292  * @newNSet: 		the pointer to new nodes set.
       
   293  * @op: 		the operation type.
       
   294  *
       
   295  * Adds @newNSet to the @nset as child using operation @op. 
       
   296  *
       
   297  * Returns the pointer to combined nodes set or NULL if an error 
       
   298  * occurs.
       
   299  */
       
   300 EXPORT_C
       
   301 xmlSecNodeSetPtr	
       
   302 xmlSecNodeSetAddList(xmlSecNodeSetPtr nset, xmlSecNodeSetPtr newNSet, xmlSecNodeSetOp op) {
       
   303     xmlSecNodeSetPtr tmp1, tmp2;
       
   304 
       
   305     xmlSecAssert2(newNSet != NULL, NULL);
       
   306     
       
   307     tmp1 = xmlSecNodeSetCreate(newNSet->doc, NULL, xmlSecNodeSetList);
       
   308     if(tmp1 == NULL) {
       
   309 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   310 		    NULL,
       
   311 		    "xmlSecNodeSetCreate",
       
   312 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   313 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   314 	return(NULL);
       
   315     }
       
   316     tmp1->children = newNSet;
       
   317     
       
   318     tmp2 = xmlSecNodeSetAdd(nset, tmp1, op);
       
   319     if(tmp2 == NULL) {
       
   320 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   321 		    NULL,
       
   322 		    "xmlSecNodeSetAdd",
       
   323 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   324 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   325 	xmlSecNodeSetDestroy(tmp1);
       
   326 	return(NULL);
       
   327     }
       
   328     return(tmp2);
       
   329 }
       
   330 
       
   331  
       
   332 /**
       
   333  * xmlSecNodeSetWalk:
       
   334  * @nset: 		the pointer to node set.
       
   335  * @walkFunc: 		the callback functions.
       
   336  * @data: 		the application specific data passed to the @walkFunc.
       
   337  *
       
   338  * Calls the function @walkFunc once per each node in the nodes set @nset.
       
   339  * If the @walkFunc returns a negative value, then the walk procedure 
       
   340  * is interrupted.
       
   341  *
       
   342  * Returns 0 on success or a negative value if an error occurs.
       
   343  */
       
   344 EXPORT_C
       
   345 int
       
   346 xmlSecNodeSetWalk(xmlSecNodeSetPtr nset, xmlSecNodeSetWalkCallback walkFunc, void* data) {
       
   347     xmlNodePtr cur;
       
   348     int ret = 0;
       
   349     
       
   350     xmlSecAssert2(nset != NULL, -1);
       
   351     xmlSecAssert2(nset->doc != NULL, -1);
       
   352     xmlSecAssert2(walkFunc != NULL, -1);
       
   353 
       
   354     /* special cases */
       
   355     if(nset->nodes != NULL) {
       
   356 	int i;
       
   357 
       
   358 	switch(nset->type) {
       
   359 	case xmlSecNodeSetNormal:
       
   360 	case xmlSecNodeSetTree:
       
   361 	case xmlSecNodeSetTreeWithoutComments:
       
   362 	    for(i = 0; (ret >= 0) && (i < nset->nodes->nodeNr); ++i) {
       
   363 		ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, 
       
   364 		    nset->nodes->nodeTab[i], 
       
   365 		    xmlSecGetParent(nset->nodes->nodeTab[i]));
       
   366 	    }
       
   367 	    return(ret);
       
   368 	default:
       
   369 	    break;
       
   370 	}
       
   371     }
       
   372     
       
   373     for(cur = nset->doc->children; (cur != NULL) && (ret >= 0); cur = cur->next) {
       
   374 	ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, cur, xmlSecGetParent(cur));
       
   375     }
       
   376     return(ret);
       
   377 }
       
   378 
       
   379 static int
       
   380 xmlSecNodeSetWalkRecursive(xmlSecNodeSetPtr nset, xmlSecNodeSetWalkCallback walkFunc, 
       
   381 			    void* data, xmlNodePtr cur, xmlNodePtr parent) {
       
   382     int ret;
       
   383 
       
   384     xmlSecAssert2(nset != NULL, -1);
       
   385     xmlSecAssert2(cur != NULL, -1);
       
   386     xmlSecAssert2(walkFunc != NULL, -1);
       
   387     
       
   388     /* the node itself */
       
   389     if(xmlSecNodeSetContains(nset, cur, parent)) {
       
   390 	ret = walkFunc(nset, cur, parent, data);
       
   391 	
       
   392 	if(ret < 0) {
       
   393 	    return(ret);
       
   394 	}
       
   395     }
       
   396 	
       
   397     /* element node has attributes, namespaces  */	
       
   398     if(cur->type == XML_ELEMENT_NODE) {
       
   399         xmlAttrPtr attr;
       
   400 	xmlNodePtr node;
       
   401 	xmlNsPtr ns, tmp;
       
   402 	
       
   403         attr = (xmlAttrPtr)cur->properties;
       
   404         while(attr != NULL) {
       
   405 	    if(xmlSecNodeSetContains(nset, (xmlNodePtr)attr, cur)) {
       
   406 		ret = walkFunc(nset, (xmlNodePtr)attr, cur, data);
       
   407 		if(ret < 0) {
       
   408 		    return(ret);
       
   409 		}
       
   410 	    }
       
   411 	    attr = attr->next;
       
   412 	}
       
   413 
       
   414 	node = cur;
       
   415 	while(node != NULL) {
       
   416     	    ns = node->nsDef;
       
   417     	    while(ns != NULL) {
       
   418 		tmp = xmlSearchNs(nset->doc, cur, ns->prefix);
       
   419 		if((tmp == ns) && xmlSecNodeSetContains(nset, (xmlNodePtr)ns, cur)) {
       
   420 		    ret = walkFunc(nset, (xmlNodePtr)ns, cur, data);
       
   421 		    if(ret < 0) {
       
   422 			return(ret);
       
   423 		    }
       
   424 		}
       
   425 		ns = ns->next;
       
   426 	    }
       
   427 	    node = node->parent;
       
   428 	}
       
   429     }
       
   430 
       
   431     /* element and document nodes have children */
       
   432     if((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE)) {
       
   433 	xmlNodePtr node;
       
   434 	
       
   435 	node = cur->children;
       
   436 	while(node != NULL) {
       
   437 	    ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, node, cur);
       
   438 	    if(ret < 0) {
       
   439 		return(ret);
       
   440 	    }
       
   441 	    node = node->next;
       
   442 	}
       
   443     }
       
   444     return(0);
       
   445 }
       
   446 
       
   447 /**
       
   448  * xmlSecNodeSetGetChildren:
       
   449  * @doc: 		the pointer to an XML document.
       
   450  * @parent:	 	the pointer to parent XML node or NULL if we want to include all document nodes.
       
   451  * @withComments: 	the flag include  comments or not.
       
   452  * @invert: 		the "invert" flag.
       
   453  *
       
   454  * Creates a new nodes set that contains:
       
   455  *  - if @withComments is not 0 and @invert is 0:
       
   456  *    all nodes in the @parent subtree;
       
   457  *  - if @withComments is 0 and @invert is 0:
       
   458  *    all nodes in the @parent subtree except comment nodes;
       
   459  *  - if @withComments is not 0 and @invert not is 0:
       
   460  *    all nodes in the @doc except nodes in the @parent subtree;
       
   461  *  - if @withComments is 0 and @invert is 0:
       
   462  *    all nodes in the @doc except nodes in the @parent subtree 
       
   463  *    and comment nodes.
       
   464  *
       
   465  * Returns pointer to the newly created #xmlSecNodeSet structure
       
   466  * or NULL if an error occurs.
       
   467  */
       
   468 EXPORT_C
       
   469 xmlSecNodeSetPtr	
       
   470 xmlSecNodeSetGetChildren(xmlDocPtr doc, const xmlNodePtr parent, int withComments, int invert) {
       
   471     xmlNodeSetPtr nodes;
       
   472     xmlSecNodeSetType type;
       
   473     xmlSecNodeSetPtr result = NULL;
       
   474 
       
   475     xmlSecAssert2(doc != NULL, NULL);
       
   476         
       
   477     nodes = xmlXPathNodeSetCreate(parent);
       
   478     if(nodes == NULL) {
       
   479 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   480 		    NULL,
       
   481 		    "xmlXPathNodeSetCreate",
       
   482 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   483 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   484 	return(NULL);
       
   485     }	
       
   486     
       
   487     /* if parent is NULL then we add all the doc children */
       
   488     if(parent == NULL) {
       
   489 	xmlNodePtr cur;
       
   490 	for(cur = doc->children; cur != NULL; cur = cur->next) {
       
   491 	    if(withComments || (cur->type != XML_COMMENT_NODE)) {
       
   492 	        xmlXPathNodeSetAdd(nodes, cur);
       
   493 	    }
       
   494 	}
       
   495     }
       
   496 
       
   497     if(withComments && invert) {
       
   498 	type = xmlSecNodeSetTreeInvert;
       
   499     } else if(withComments && !invert) {
       
   500 	type = xmlSecNodeSetTree;
       
   501     } else if(!withComments && invert) {
       
   502 	type = xmlSecNodeSetTreeWithoutCommentsInvert;
       
   503     } else { /* if(!withComments && !invert) */
       
   504 	type = xmlSecNodeSetTreeWithoutComments;
       
   505     }
       
   506 
       
   507     result = xmlSecNodeSetCreate(doc, nodes, type);
       
   508     if ( !result )
       
   509         {
       
   510         xmlXPathFreeNodeSet( nodes );   
       
   511         }
       
   512     return result;
       
   513 }
       
   514 
       
   515 static int
       
   516 xmlSecNodeSetDumpTextNodesWalkCallback(xmlSecNodeSetPtr nset, xmlNodePtr cur, 
       
   517 				   xmlNodePtr parent, 
       
   518 				   void* data) {
       
   519     xmlSecAssert2(nset != NULL, -1);
       
   520     xmlSecAssert2(cur != NULL, -1);
       
   521     xmlSecAssert2(data != NULL, -1);
       
   522 
       
   523     if(cur->type == XML_TEXT_NODE) {
       
   524 	xmlOutputBufferWriteString((xmlOutputBufferPtr)data, 
       
   525 				    (char*)(cur->content)); 
       
   526     }
       
   527     return(0);
       
   528 }
       
   529 
       
   530 /**
       
   531  * xmlSecNodeSetDumpTextNodes:
       
   532  * @nset: 		the pointer to node set.
       
   533  * @out:		the output buffer.
       
   534  *
       
   535  * Dumps content of all the text nodes from @nset to @out.
       
   536  *
       
   537  * Returns 0 on success or a negative value otherwise.
       
   538  */
       
   539 EXPORT_C
       
   540 int 
       
   541 xmlSecNodeSetDumpTextNodes(xmlSecNodeSetPtr nset, xmlOutputBufferPtr out) {
       
   542     xmlSecAssert2(nset != NULL, -1);
       
   543     xmlSecAssert2(out != NULL, -1);
       
   544 
       
   545     return(xmlSecNodeSetWalk(nset, xmlSecNodeSetDumpTextNodesWalkCallback, out));
       
   546 }
       
   547 
       
   548 /**
       
   549  * xmlSecNodeSetDebugDump: 
       
   550  * @nset: 		the pointer to node set.
       
   551  * @output: 		the pointer to output FILE.
       
   552  * 
       
   553  * Prints information about @nset to the @output.
       
   554  */
       
   555 EXPORT_C
       
   556 void
       
   557 xmlSecNodeSetDebugDump(xmlSecNodeSetPtr nset, FILE *output) {
       
   558     int i, l;
       
   559     xmlNodePtr cur;
       
   560 
       
   561     xmlSecAssert(nset != NULL);
       
   562     xmlSecAssert(output != NULL);
       
   563 
       
   564     fprintf(output, "== Nodes set ");
       
   565     switch(nset->type) {
       
   566     case xmlSecNodeSetNormal:
       
   567 	fprintf(output, "(xmlSecNodeSetNormal)\n");
       
   568 	break;
       
   569     case xmlSecNodeSetInvert:
       
   570 	fprintf(output, "(xmlSecNodeSetInvert)\n");
       
   571 	break;
       
   572     case xmlSecNodeSetTree:
       
   573 	fprintf(output, "(xmlSecNodeSetTree)\n");
       
   574 	break;
       
   575     case xmlSecNodeSetTreeWithoutComments:
       
   576 	fprintf(output, "(xmlSecNodeSetTreeWithoutComments)\n");
       
   577 	break;
       
   578     case xmlSecNodeSetTreeInvert:
       
   579 	fprintf(output, "(xmlSecNodeSetTreeInvert)\n");
       
   580 	break;
       
   581     case xmlSecNodeSetTreeWithoutCommentsInvert:
       
   582 	fprintf(output, "(xmlSecNodeSetTreeWithoutCommentsInvert)\n");
       
   583 	break;
       
   584     case xmlSecNodeSetList:
       
   585 	fprintf(output, "(xmlSecNodeSetList)\n");
       
   586 	fprintf(output, ">>>\n");
       
   587 	xmlSecNodeSetDebugDump(nset->children, output);
       
   588 	fprintf(output, "<<<\n");
       
   589 	return;
       
   590     default:
       
   591 	fprintf(output, "(unknown=%d)\n", nset->type);
       
   592 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   593 		    NULL,
       
   594 		    NULL,
       
   595 		    XMLSEC_ERRORS_R_INVALID_TYPE,
       
   596 		    "type=%d", nset->type);
       
   597     }
       
   598         
       
   599     l = xmlXPathNodeSetGetLength(nset->nodes);
       
   600     for(i = 0; i < l; ++i) {
       
   601 	cur = xmlXPathNodeSetItem(nset->nodes, i);
       
   602 	if(cur->type != XML_NAMESPACE_DECL) {
       
   603 	    fprintf(output, "%d: %s\n", cur->type, 
       
   604 		(cur->name) ? cur->name : BAD_CAST "null");
       
   605 	} else {
       
   606 	    xmlNsPtr ns = (xmlNsPtr)cur;
       
   607 	    fprintf(output, "%d: %s=%s (%s:%s)\n", cur->type, 
       
   608 		(ns->prefix) ? ns->prefix : BAD_CAST "null",
       
   609 		(ns->href) ? ns->href : BAD_CAST "null",
       
   610 		(((xmlNodePtr)ns->next)->ns && 
       
   611 		 ((xmlNodePtr)ns->next)->ns->prefix) ? 
       
   612 		  ((xmlNodePtr)ns->next)->ns->prefix : BAD_CAST "null",		
       
   613 		((xmlNodePtr)ns->next)->name);
       
   614 	}
       
   615     }
       
   616 }