xmlsecurityengine/xmlsec/src/xmlsec_xmltree.c
changeset 0 e35f40988205
child 12 d10d750052f0
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * Common XML Doc utility functions
       
     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 #include <ctype.h>
       
    17  
       
    18 #include <libxml2_tree.h>
       
    19 #include <libxml2_valid.h>
       
    20 #include <libxml2_xpath.h>
       
    21 #include <libxml2_xpathinternals.h>
       
    22 #include <libxml2_globals.h>
       
    23  
       
    24 #include "xmlsec_xmlsec.h"
       
    25 #include "xmlsec_xmltree.h"
       
    26 #include "xmlsec_parser.h"
       
    27 #include "xmlsec_private.h"
       
    28 #include "xmlsec_base64.h"
       
    29 #include "xmlsec_errors.h"
       
    30 #include "xmlsec_templates.h"
       
    31 
       
    32 /**
       
    33  * xmlSecFindChild:
       
    34  * @parent: 		the pointer to XML node.
       
    35  * @name: 		the name.
       
    36  * @ns: 		the namespace href (may be NULL).
       
    37  *
       
    38  * Searches a direct child of the @parent node having given name and 
       
    39  * namespace href.
       
    40  * 
       
    41  * Returns the pointer to the found node or NULL if an error occurs or 
       
    42  * node is not found.
       
    43  */
       
    44 EXPORT_C
       
    45 xmlNodePtr
       
    46 xmlSecFindChild(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
       
    47     xmlNodePtr cur;
       
    48         
       
    49     xmlSecAssert2(parent != NULL, NULL);
       
    50     xmlSecAssert2(name != NULL, NULL);
       
    51     
       
    52     cur = parent->children;
       
    53     while(cur != NULL) {
       
    54         if(cur->type == XML_ELEMENT_NODE) {
       
    55 	    if(xmlSecCheckNodeName(cur, name, ns)) {
       
    56 		return(cur);
       
    57 	    }
       
    58 	}
       
    59 	cur = cur->next;
       
    60     }
       
    61     return(NULL);
       
    62 }
       
    63 
       
    64 /**
       
    65  * xmlSecFindParent:
       
    66  * @cur: 		the pointer to an XML node.
       
    67  * @name: 		the name.
       
    68  * @ns: 		the namespace href (may be NULL).
       
    69  *
       
    70  * Searches the ancestors axis of the @cur node for a node having given name 
       
    71  * and namespace href.
       
    72  * 
       
    73  * Returns the pointer to the found node or NULL if an error occurs or 
       
    74  * node is not found.
       
    75  */
       
    76 EXPORT_C
       
    77 xmlNodePtr
       
    78 xmlSecFindParent(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
       
    79     xmlSecAssert2(cur != NULL, NULL);
       
    80     xmlSecAssert2(name != NULL, NULL);        
       
    81 
       
    82     if(xmlSecCheckNodeName(cur, name, ns)) {
       
    83 	return(cur);
       
    84     } else if(cur->parent != NULL) {
       
    85 	return(xmlSecFindParent(cur->parent, name, ns));
       
    86     }
       
    87     return(NULL);
       
    88 }
       
    89 
       
    90 /**
       
    91  * xmlSecFindNode:
       
    92  * @parent: 		the pointer to XML node.
       
    93  * @name: 		the name.
       
    94  * @ns: 		the namespace href (may be NULL).
       
    95  *
       
    96  * Searches all children of the @parent node having given name and 
       
    97  * namespace href.
       
    98  * 
       
    99  * Returns the pointer to the found node or NULL if an error occurs or 
       
   100  * node is not found.
       
   101  */
       
   102 EXPORT_C
       
   103 xmlNodePtr		
       
   104 xmlSecFindNode(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
       
   105     xmlNodePtr cur;
       
   106     xmlNodePtr ret;
       
   107         
       
   108     xmlSecAssert2(name != NULL, NULL); 
       
   109     
       
   110     cur = parent;
       
   111     while(cur != NULL) {
       
   112         if((cur->type == XML_ELEMENT_NODE) && xmlSecCheckNodeName(cur, name, ns)) {
       
   113 	    return(cur);
       
   114 	}
       
   115 	if(cur->children != NULL) {
       
   116 	    ret = xmlSecFindNode(cur->children, name, ns);
       
   117 	    if(ret != NULL) {
       
   118 	        return(ret);	    
       
   119 	    }
       
   120 	}
       
   121 	cur = cur->next;
       
   122     }
       
   123     return(NULL);
       
   124 }
       
   125 
       
   126 /**
       
   127  * xmlSecGetNodeNsHref:
       
   128  * @cur:		the pointer to node.
       
   129  *
       
   130  * Get's node's namespace href.
       
   131  *
       
   132  * Returns node's namespace href.
       
   133  */
       
   134 EXPORT_C
       
   135 const xmlChar* 
       
   136 xmlSecGetNodeNsHref(const xmlNodePtr cur) {
       
   137     xmlNsPtr ns;
       
   138     
       
   139     xmlSecAssert2(cur != NULL, NULL);
       
   140     
       
   141     /* do we have a namespace in the node? */
       
   142     if(cur->ns != NULL) {
       
   143 	return(cur->ns->href);
       
   144     }
       
   145     
       
   146     /* search for default namespace */
       
   147     ns = xmlSearchNs(cur->doc, cur, NULL);
       
   148     if(ns != NULL) {
       
   149 	return(ns->href);
       
   150     }
       
   151 	
       
   152     return(NULL);
       
   153 }
       
   154 
       
   155 /** 
       
   156  * xmlSecCheckNodeName:
       
   157  * @cur: 		the pointer to an XML node.
       
   158  * @name: 		the name,
       
   159  * @ns: 		the namespace href.
       
   160  *
       
   161  * Checks that the node has a given name and a given namespace href.
       
   162  *
       
   163  * Returns 1 if the node matches or 0 otherwise.
       
   164  */
       
   165 EXPORT_C
       
   166 int
       
   167 xmlSecCheckNodeName(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
       
   168     xmlSecAssert2(cur != NULL, 0);
       
   169     
       
   170     return(xmlStrEqual(cur->name, name) && 
       
   171 	   xmlStrEqual(xmlSecGetNodeNsHref(cur), ns));
       
   172 }
       
   173 
       
   174 /**
       
   175  * xmlSecAddChild:
       
   176  * @parent: 		the pointer to an XML node.
       
   177  * @name: 		the new node name.
       
   178  * @ns: 		the new node namespace.
       
   179  *
       
   180  * Adds a child to the node @parent with given @name and namespace @ns.
       
   181  *
       
   182  * Returns pointer to the new node or NULL if an error occurs.
       
   183  */
       
   184 EXPORT_C
       
   185 xmlNodePtr		
       
   186 xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
       
   187     xmlNodePtr cur;
       
   188     xmlNodePtr text;
       
   189 
       
   190     xmlSecAssert2(parent != NULL, NULL);
       
   191     xmlSecAssert2(name != NULL, NULL);        
       
   192 
       
   193     if(xmlGetNewLineFlag() && parent->children == NULL) {
       
   194 	text = xmlNewText(xmlSecStringCR); 
       
   195         if(text == NULL) {	
       
   196 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   197 			NULL,
       
   198 			"xmlNewText",
       
   199 			XMLSEC_ERRORS_R_XML_FAILED,
       
   200 			XMLSEC_ERRORS_NO_MESSAGE);
       
   201 	    return(NULL);
       
   202 	}
       
   203 	xmlAddChild(parent, text);
       
   204     }
       
   205 
       
   206     cur = xmlNewChild(parent, NULL, name, NULL);
       
   207     if(cur == NULL) {
       
   208 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   209 		    NULL,
       
   210 		    "xmlNewChild",
       
   211 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   212 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   213 	return(NULL);
       
   214     }
       
   215 
       
   216     /* namespaces support */
       
   217     if(ns != NULL) {
       
   218 	xmlNsPtr nsPtr;
       
   219 	
       
   220 	nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
       
   221 	if((nsPtr == NULL) || !xmlStrEqual(nsPtr->href, ns)) {
       
   222 	    nsPtr = xmlNewNs(cur, ns, NULL);
       
   223 	}
       
   224 	xmlSetNs(cur, nsPtr);
       
   225     }
       
   226     
       
   227     if(xmlGetNewLineFlag())
       
   228         {
       
   229         text = xmlNewText(xmlSecStringCR); 
       
   230         if(text == NULL) {	
       
   231     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   232     		    NULL,
       
   233     		    "xmlNewText",
       
   234     		    XMLSEC_ERRORS_R_XML_FAILED,
       
   235     		    XMLSEC_ERRORS_NO_MESSAGE);
       
   236     	return(NULL);
       
   237         }
       
   238         xmlAddChild(parent, text);
       
   239         }
       
   240     return(cur);
       
   241 }
       
   242 
       
   243 /**
       
   244  * xmlSecAddChildNode:
       
   245  * @parent: 		the pointer to an XML node.
       
   246  * @child: 		the new node.
       
   247  *
       
   248  * Adds @child node to the @parent node.
       
   249  *
       
   250  * Returns pointer to the new node or NULL if an error occurs.
       
   251  */
       
   252 EXPORT_C
       
   253 xmlNodePtr		
       
   254 xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) {
       
   255     xmlNodePtr text;
       
   256 
       
   257     xmlSecAssert2(parent != NULL, NULL);
       
   258     xmlSecAssert2(child != NULL, NULL);        
       
   259 
       
   260     if(xmlGetNewLineFlag() && parent->children == NULL) {
       
   261 	text = xmlNewText(xmlSecStringCR); 
       
   262         if(text == NULL) {	
       
   263 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   264 			NULL,
       
   265 			"xmlNewText",
       
   266 			XMLSEC_ERRORS_R_XML_FAILED,
       
   267 			XMLSEC_ERRORS_NO_MESSAGE);
       
   268 	    return(NULL);
       
   269 	}
       
   270 	xmlAddChild(parent, text);
       
   271     }
       
   272 
       
   273     xmlAddChild(parent, child);
       
   274 
       
   275     if(xmlGetNewLineFlag())
       
   276         {
       
   277         text = xmlNewText(xmlSecStringCR); 
       
   278         if(text == NULL) {	
       
   279     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   280     		    NULL,
       
   281     		    "xmlNewText",
       
   282     		    XMLSEC_ERRORS_R_XML_FAILED,
       
   283     		    XMLSEC_ERRORS_NO_MESSAGE);
       
   284     	return(NULL);
       
   285         }
       
   286         xmlAddChild(parent, text);
       
   287         }
       
   288 
       
   289     return(child);
       
   290 }
       
   291 
       
   292 /**
       
   293  * xmlSecAddNextSibling
       
   294  * @node: 		the pointer to an XML node.
       
   295  * @name: 		the new node name.
       
   296  * @ns: 		the new node namespace.
       
   297  *
       
   298  * Adds next sibling to the node @node with given @name and namespace @ns.
       
   299  *
       
   300  * Returns pointer to the new node or NULL if an error occurs.
       
   301  */
       
   302 EXPORT_C
       
   303 xmlNodePtr
       
   304 xmlSecAddNextSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
       
   305     xmlNodePtr cur;
       
   306     xmlNodePtr text;
       
   307 
       
   308     xmlSecAssert2(node != NULL, NULL);
       
   309     xmlSecAssert2(name != NULL, NULL);    
       
   310 
       
   311     cur = xmlNewNode(NULL, name);
       
   312     if(cur == NULL) {
       
   313 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   314 		    NULL,
       
   315 		    "xmlNewNode",
       
   316 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   317 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   318 	return(NULL);
       
   319     }
       
   320     xmlAddNextSibling(node, cur);
       
   321 
       
   322     /* namespaces support */
       
   323     if(ns != NULL) {
       
   324 	xmlNsPtr nsPtr;
       
   325 	
       
   326 	nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
       
   327 	if((nsPtr == NULL) || !xmlStrEqual(nsPtr->href, ns)) {
       
   328 	    nsPtr = xmlNewNs(cur, ns, NULL);
       
   329 	}
       
   330 	xmlSetNs(cur, nsPtr);
       
   331     }
       
   332 
       
   333     if(xmlGetNewLineFlag())
       
   334         {
       
   335         text = xmlNewText(xmlSecStringCR); 
       
   336         if(text == NULL) {	
       
   337     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   338     		    NULL,
       
   339     		    "xmlNewText",
       
   340     		    XMLSEC_ERRORS_R_XML_FAILED,
       
   341     		    XMLSEC_ERRORS_NO_MESSAGE);
       
   342     	return(NULL);
       
   343         }
       
   344         xmlAddNextSibling(node, text);
       
   345         } 
       
   346     
       
   347     return(cur);
       
   348 }
       
   349 
       
   350 /**
       
   351  * xmlSecAddPrevSibling
       
   352  * @node: 		the pointer to an XML node.
       
   353  * @name: 		the new node name.
       
   354  * @ns: 		the new node namespace.
       
   355  *
       
   356  * Adds prev sibling to the node @node with given @name and namespace @ns.
       
   357  *
       
   358  * Returns pointer to the new node or NULL if an error occurs.
       
   359  */
       
   360 EXPORT_C
       
   361 xmlNodePtr
       
   362 xmlSecAddPrevSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
       
   363     xmlNodePtr cur;
       
   364     xmlNodePtr text;
       
   365 
       
   366     xmlSecAssert2(node != NULL, NULL);
       
   367     xmlSecAssert2(name != NULL, NULL);    
       
   368 
       
   369     cur = xmlNewNode(NULL, name);
       
   370     if(cur == NULL) {
       
   371 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   372 		    NULL,
       
   373 		    "xmlNewNode",
       
   374 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   375 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   376 	return(NULL);
       
   377     }
       
   378     xmlAddPrevSibling(node, cur);
       
   379 
       
   380     /* namespaces support */
       
   381     if(ns != NULL) {
       
   382 	xmlNsPtr nsPtr;
       
   383 	
       
   384 	nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
       
   385 	if((nsPtr == NULL) || !xmlStrEqual(nsPtr->href, ns)) {
       
   386 	    nsPtr = xmlNewNs(cur, ns, NULL);
       
   387 	    if (nsPtr == NULL)
       
   388 	        return(NULL);
       
   389 	}
       
   390 	xmlSetNs(cur, nsPtr);
       
   391     }
       
   392 
       
   393     if(xmlGetNewLineFlag())
       
   394         {
       
   395         text = xmlNewText(xmlSecStringCR); 
       
   396         if(text == NULL) {	
       
   397     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   398     		    NULL,
       
   399     		    "xmlNewText",
       
   400     		    XMLSEC_ERRORS_R_XML_FAILED,
       
   401     		    XMLSEC_ERRORS_NO_MESSAGE);
       
   402     	return(NULL);
       
   403         }
       
   404         xmlAddPrevSibling(node, text);
       
   405         }
       
   406     return(cur);
       
   407 }
       
   408 
       
   409 /**
       
   410  * xmlSecGetNextElementNode:
       
   411  * @cur: 		the pointer to an XML node.
       
   412  *
       
   413  * Seraches for the next element node.
       
   414  *
       
   415  * Returns the pointer to next element node or NULL if it is not found.
       
   416  */
       
   417 EXPORT_C
       
   418 xmlNodePtr
       
   419 xmlSecGetNextElementNode(xmlNodePtr cur) {
       
   420     
       
   421     while((cur != NULL) && (cur->type != XML_ELEMENT_NODE)) {
       
   422 	cur = cur->next;
       
   423     }
       
   424     return(cur);
       
   425 }
       
   426 
       
   427 /**
       
   428  * xmlSecReplaceNode:
       
   429  * @node: 		the current node.
       
   430  * @newNode: 		the new node.
       
   431  * 
       
   432  * Swaps the @node and @newNode in the XML tree.
       
   433  *
       
   434  * Returns 0 on success or a negative value if an error occurs.
       
   435  */
       
   436 EXPORT_C
       
   437 int
       
   438 xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode) {
       
   439     xmlNodePtr oldNode;
       
   440     int restoreRoot = 0;
       
   441     
       
   442     xmlSecAssert2(node != NULL, -1);
       
   443     xmlSecAssert2(newNode != NULL, -1);    
       
   444 
       
   445     /* fix documents children if necessary first */
       
   446     if((node->doc != NULL) && (node->doc->children == node)) {
       
   447 	node->doc->children = node->next;
       
   448 	restoreRoot = 1;
       
   449     }
       
   450     if((newNode->doc != NULL) && (newNode->doc->children == newNode)) {
       
   451 	newNode->doc->children = newNode->next;
       
   452     }
       
   453 
       
   454     oldNode = xmlReplaceNode(node, newNode);
       
   455     if(oldNode == NULL) {
       
   456 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   457 		    NULL,
       
   458                     "xmlReplaceNode",
       
   459 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   460 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   461 	return(-1);
       
   462     }
       
   463 
       
   464     if(restoreRoot != 0) {
       
   465 	xmlDocSetRootElement(oldNode->doc, newNode);
       
   466     }
       
   467 
       
   468     xmlFreeNode(oldNode);
       
   469     return(0);
       
   470 }
       
   471 
       
   472 /**
       
   473  * xmlSecReplaceContent
       
   474  * @node: 		the current node.
       
   475  * @newNode: 		the new node.
       
   476  * 
       
   477  * Swaps the content of @node and @newNode.
       
   478  *
       
   479  * Returns 0 on success or a negative value if an error occurs.
       
   480  */
       
   481 EXPORT_C
       
   482 int
       
   483 xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode) {
       
   484     xmlSecAssert2(node != NULL, -1);
       
   485     xmlSecAssert2(newNode != NULL, -1);  
       
   486 
       
   487     xmlUnlinkNode(newNode);
       
   488     xmlSetTreeDoc(newNode, node->doc);
       
   489     xmlNodeSetContent(node, NULL);
       
   490     xmlAddChild(node, newNode);
       
   491     xmlSetTreeDoc(newNode, node->doc);
       
   492 
       
   493     return(0);
       
   494 }
       
   495 
       
   496 
       
   497 /**
       
   498  * xmlSecReplaceNodeBuffer:
       
   499  * @node: 		the current node.
       
   500  * @buffer: 		the XML data.
       
   501  * @size: 		the XML data size.
       
   502  * 
       
   503  * Swaps the @node and the parsed XML data from the @buffer in the XML tree.
       
   504  *
       
   505  * Returns 0 on success or a negative value if an error occurs.
       
   506  */
       
   507 EXPORT_C
       
   508 int
       
   509 xmlSecReplaceNodeBuffer(xmlNodePtr node, 
       
   510 			const xmlSecByte *buffer, xmlSecSize size) {
       
   511     xmlNodePtr results = NULL;
       
   512     xmlNodePtr next = NULL;
       
   513     xmlNodePtr tmp = NULL; // MK added
       
   514 
       
   515     xmlSecAssert2(node != NULL, -1);
       
   516     xmlSecAssert2(node->parent != NULL, -1);
       
   517 
       
   518     /* parse buffer in the context of node's parent */
       
   519     if(xmlParseInNodeContext(node->parent, (const char*)buffer, size, XML_PARSE_NODICT, &results) != XML_ERR_OK) {
       
   520         xmlSecError(XMLSEC_ERRORS_HERE,
       
   521                     NULL,
       
   522                     "xmlParseInNodeContext",
       
   523                     XMLSEC_ERRORS_R_XML_FAILED,
       
   524                     "Failed to parse content");
       
   525         return(-1);         
       
   526     }
       
   527     
       
   528     if(results == NULL && node->parent->type == XML_DOCUMENT_NODE)
       
   529         {
       
   530         tmp = node->last;
       
   531         xmlUnlinkNode(tmp);
       
   532         results = tmp;
       
   533         }
       
   534     
       
   535     /* add new nodes */
       
   536     while (results != NULL) {
       
   537         next = results->next;
       
   538         xmlAddPrevSibling(node, results);
       
   539         results = next;
       
   540     }
       
   541         
       
   542     /* remove old node */
       
   543     xmlUnlinkNode(node);
       
   544     xmlFreeNode(node);  
       
   545 
       
   546     return(0);
       
   547 }
       
   548 
       
   549 /**
       
   550  * xmlSecAddIDs:
       
   551  * @doc: 		the pointer to an XML document.
       
   552  * @cur: 		the pointer to an XML node.
       
   553  * @ids: 		the pointer to a NULL terminated list of ID attributes.
       
   554  *
       
   555  * Walks thru all children of the @cur node and adds all attributes 
       
   556  * from the @ids list to the @doc document IDs attributes hash.
       
   557  */
       
   558 EXPORT_C
       
   559 void	
       
   560 xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr cur, const xmlChar** ids) {
       
   561     xmlNodePtr children = NULL;
       
   562 
       
   563     xmlSecAssert(doc != NULL);
       
   564     xmlSecAssert(ids != NULL);    
       
   565     
       
   566     if((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
       
   567 	xmlAttrPtr attr;
       
   568 	xmlAttrPtr tmp;
       
   569 	int i;
       
   570 	xmlChar* name;
       
   571 	
       
   572 	for(attr = cur->properties; attr != NULL; attr = attr->next) {
       
   573 	    for(i = 0; ids[i] != NULL; ++i) {
       
   574 		if(xmlStrEqual(attr->name, ids[i])) {
       
   575 		    name = xmlNodeListGetString(doc, attr->children, 1);
       
   576 		    if(name != NULL) {
       
   577 			tmp = xmlGetID(doc, name);
       
   578 			if(tmp == NULL) {
       
   579 			    xmlAddID(NULL, doc, name, attr);
       
   580 			} else if(tmp != attr) {
       
   581 			    xmlSecError(XMLSEC_ERRORS_HERE,
       
   582 					NULL,
       
   583 					NULL,
       
   584 					XMLSEC_ERRORS_R_INVALID_DATA,
       
   585 					"id=%s already defined", 
       
   586 					xmlSecErrorsSafeString(name));
       
   587 			}
       
   588 			xmlFree(name);
       
   589 		    }		    
       
   590 		}
       
   591 	    }
       
   592 	}
       
   593 	
       
   594 	children = cur->children;
       
   595     } else if(cur == NULL) {
       
   596 	children = doc->children;
       
   597     }
       
   598     
       
   599     while(children != NULL) {
       
   600 	if(children->type == XML_ELEMENT_NODE) {
       
   601 	    xmlSecAddIDs(doc, children, ids);
       
   602 	}
       
   603 	children = children->next;
       
   604     }
       
   605 }
       
   606 
       
   607 /**
       
   608  * xmlSecGenerateAndAddID:
       
   609  * @node:			the node to ID attr to.
       
   610  * @attrName:			the ID attr name.
       
   611  * @prefix:			the prefix to add to the generated ID (can be NULL).
       
   612  * @len:			the length of ID.
       
   613  *
       
   614  * Generates a unique ID in the format <@prefix>base64-encoded(@len random bytes)
       
   615  * and puts it in the attribute @attrName.
       
   616  *
       
   617  * Returns 0 on success or a negative value if an error occurs.
       
   618  */
       
   619 EXPORT_C
       
   620 int 
       
   621 xmlSecGenerateAndAddID(xmlNodePtr node, const xmlChar* attrName, const xmlChar* prefix, xmlSecSize len) {
       
   622     xmlChar* id;
       
   623     int count;
       
   624     
       
   625     xmlSecAssert2(node != NULL, -1);    
       
   626     xmlSecAssert2(attrName != NULL, -1);    
       
   627 
       
   628     /* we will try 5 times before giving up */
       
   629     for(count = 0; count < 5; count++) {
       
   630 	id = xmlSecGenerateID(prefix, len);
       
   631 	if(id == NULL) {
       
   632 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   633 		        NULL,
       
   634 			"xmlSecGenerateID",
       
   635 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   636 			XMLSEC_ERRORS_NO_MESSAGE);
       
   637 	    return(-1);
       
   638 	}
       
   639 
       
   640 	if((node->doc == NULL) || (xmlGetID(node->doc, id) == NULL)) {
       
   641 	    /* this is a unique ID in the document and we can use it */
       
   642 	    if(xmlSetProp(node, attrName, id) == NULL) {
       
   643 	        xmlSecError(XMLSEC_ERRORS_HERE,
       
   644 		            NULL,
       
   645 		    	    "xmlSetProp",
       
   646 			    XMLSEC_ERRORS_R_XML_FAILED,
       
   647 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   648 		xmlFree(id);
       
   649 	        return(-1);	
       
   650 	    }
       
   651 	    
       
   652 	    xmlFree(id);
       
   653 	    return(0);
       
   654 	}
       
   655 	xmlFree(id);
       
   656     }
       
   657 
       
   658     return(-1);
       
   659 }
       
   660 
       
   661 /**
       
   662  * xmlSecGenerateID:
       
   663  * @prefix:			the prefix to add to the generated ID (can be NULL).
       
   664  * @len:			the length of ID.
       
   665  *
       
   666  * Generates a unique ID in the format <@prefix>base64-encoded(@len random bytes).
       
   667  * The caller is responsible for freeing returned string using @xmlFree function.
       
   668  *
       
   669  * Returns pointer to generated ID string or NULL if an error occurs.
       
   670  */
       
   671 EXPORT_C
       
   672 xmlChar*
       
   673 xmlSecGenerateID(const xmlChar* prefix, xmlSecSize len) {
       
   674     xmlSecBuffer buffer;    
       
   675     xmlSecSize i, binLen;
       
   676     xmlChar* res;
       
   677     xmlChar* p;
       
   678     int ret;
       
   679 
       
   680     xmlSecAssert2(len > 0, NULL);    
       
   681     
       
   682     /* we will do base64 decoding later */
       
   683     binLen = (3 * len + 1) / 4;
       
   684     
       
   685     ret = xmlSecBufferInitialize(&buffer, binLen + 1);
       
   686     if(ret < 0) {
       
   687 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   688 		    NULL,
       
   689 		    "xmlSecBufferInitialize",
       
   690 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   691 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   692 	return(NULL);	
       
   693     }
       
   694     xmlSecAssert2(xmlSecBufferGetData(&buffer) != NULL, NULL);
       
   695     xmlSecAssert2(xmlSecBufferGetMaxSize(&buffer) >= binLen, NULL);
       
   696     
       
   697     ret = xmlSecBufferSetSize(&buffer, binLen);
       
   698     if(ret < 0) {
       
   699 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   700 		    NULL,
       
   701 		    "xmlSecBufferSetSize",
       
   702 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   703 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   704 	xmlSecBufferFinalize(&buffer);
       
   705 	return(NULL);	
       
   706     }
       
   707     xmlSecAssert2(xmlSecBufferGetSize(&buffer) == binLen, NULL);
       
   708     
       
   709     /* create random bytes */
       
   710     for(i = 0; i < binLen; i++) {
       
   711 	(xmlSecBufferGetData(&buffer)) [i] = (xmlSecByte) (256.0 * rand() / (RAND_MAX + 1.0));
       
   712     }
       
   713     
       
   714     /* base64 encode random bytes */
       
   715     res = xmlSecBase64Encode(xmlSecBufferGetData(&buffer), xmlSecBufferGetSize(&buffer), 0);
       
   716     if((res == NULL) || (xmlStrlen(res) == 0)) {
       
   717 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   718 		    NULL,
       
   719 		    "xmlSecBase64Encode",
       
   720 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   721 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   722 	xmlSecBufferFinalize(&buffer);
       
   723 	return(NULL);	
       
   724     }
       
   725     xmlSecBufferFinalize(&buffer);
       
   726 
       
   727     /* truncate the generated id attribute if needed */
       
   728     if(xmlStrlen(res) > (int)len) {
       
   729 	res[len] = '\0';
       
   730     }
       
   731 
       
   732     /* we need to cleanup base64 encoded id because ID attr can't have '+' or '/' characters */ 
       
   733     for(p = res; (*p) != '\0'; p++) {
       
   734 	if(((*p) == '+') || ((*p) == '/')) {
       
   735 	    (*p) = '_';
       
   736 	}
       
   737     }
       
   738     
       
   739     /* add prefix if exist */
       
   740     if(prefix) {
       
   741 	xmlChar* tmp;
       
   742 	xmlSecSize tmpLen;
       
   743 	
       
   744 	tmpLen = xmlStrlen(prefix) + xmlStrlen(res) + 1;
       
   745 	tmp = xmlMalloc(tmpLen + 1);
       
   746 	if(tmp == NULL) {
       
   747 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   748 		        NULL,
       
   749 			"xmlMalloc",
       
   750 		        XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   751 			XMLSEC_ERRORS_NO_MESSAGE);
       
   752 	    xmlFree(res);
       
   753 	    return(NULL);
       
   754 	}
       
   755 	
       
   756 	xmlSecStrPrintf(tmp, tmpLen, BAD_CAST "%s%s", prefix, res);
       
   757 	xmlFree(res);
       
   758 	res = tmp;    
       
   759     } else {
       
   760 	/* no prefix: check that ID attribute starts from a letter */
       
   761 	if(!(((res[0] >= 'A') && (res[0] <= 'Z')) || 
       
   762 	     ((res[0] >= 'a') && (res[0] <= 'z')))) {
       
   763 	     res[0] = 'A';
       
   764 	}
       
   765     }
       
   766     
       
   767     return(res);
       
   768 }
       
   769 
       
   770 
       
   771 /**
       
   772  * xmlSecCreateTree:
       
   773  * @rootNodeName:	the root node name.
       
   774  * @rootNodeNs:		the root node namespace (otpional).
       
   775  *
       
   776  * Creates a new XML tree with one root node @rootNodeName.
       
   777  *
       
   778  * Returns pointer to the newly created tree or NULL if an error occurs.
       
   779  */
       
   780 EXPORT_C
       
   781 xmlDocPtr 
       
   782 xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) {
       
   783     xmlDocPtr doc;
       
   784     xmlNodePtr root;
       
   785     xmlNsPtr ns;
       
   786     
       
   787     xmlSecAssert2(rootNodeName != NULL, NULL);
       
   788 
       
   789     /* create doc */
       
   790     doc = xmlNewDoc(BAD_CAST "1.0");
       
   791     if(doc == NULL) {
       
   792 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   793 		    NULL,
       
   794 		    "xmlNewDoc",
       
   795 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   796 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   797 	return(NULL);
       
   798     }
       
   799     
       
   800     /* create root node */
       
   801     root = xmlNewDocNode(doc, NULL, rootNodeName, NULL); 
       
   802     if(root == NULL) {
       
   803 	xmlSecError(XMLSEC_ERRORS_HERE,	
       
   804 		    NULL,
       
   805 		    "xmlNewDocNode",
       
   806 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   807 		    "node=Keys");
       
   808 	xmlFreeDoc(doc);
       
   809 	return(NULL);
       
   810     }
       
   811     xmlDocSetRootElement(doc, root);
       
   812 
       
   813     /* and set root node namespace */
       
   814     ns = xmlNewNs(root, rootNodeNs, NULL);
       
   815     if(ns == NULL) {
       
   816 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   817 		    NULL,
       
   818 		    "xmlNewNs",
       
   819 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   820 		    "ns=%s",
       
   821 		    xmlSecErrorsSafeString(rootNodeNs));
       
   822 	xmlFreeDoc(doc); 
       
   823 	return(NULL);
       
   824     }
       
   825     xmlSetNs(root, ns);
       
   826 
       
   827     return(doc);
       
   828 }
       
   829 
       
   830 /**
       
   831  * xmlSecIsEmptyNode:
       
   832  * @node:		the node to check
       
   833  *
       
   834  * Checks whethere the @node is empty (i.e. has only whitespaces children).
       
   835  *
       
   836  * Returns 1 if @node is empty, 0 otherwise or a negative value if an error occurs.
       
   837  */
       
   838 EXPORT_C
       
   839 int 
       
   840 xmlSecIsEmptyNode(xmlNodePtr node) {
       
   841     xmlChar* content;
       
   842     int res;
       
   843     
       
   844     xmlSecAssert2(node != NULL, -1);
       
   845 
       
   846     if(xmlSecGetNextElementNode(node->children) != NULL) {
       
   847 	return(0);
       
   848     }
       
   849     
       
   850     content = xmlNodeGetContent(node);
       
   851     if(content == NULL) {
       
   852 	return(1);
       
   853     }
       
   854     
       
   855     res = xmlSecIsEmptyString(content);
       
   856     xmlFree(content);
       
   857     return(res);
       
   858 }
       
   859 
       
   860 /**
       
   861  * xmlSecIsEmptyString:
       
   862  * @str:		the string to check
       
   863  *
       
   864  * Checks whethere the @str is empty (i.e. has only whitespaces children).
       
   865  *
       
   866  * Returns 1 if @str is empty, 0 otherwise or a negative value if an error occurs.
       
   867  */
       
   868 EXPORT_C
       
   869 int 
       
   870 xmlSecIsEmptyString(const xmlChar* str) {
       
   871     xmlSecAssert2(str != NULL, -1);
       
   872     
       
   873     for( ;*str != '\0'; ++str) {
       
   874 	if(!isspace((int)(*str))) {
       
   875 	    return(0);
       
   876 	}
       
   877     }
       
   878     return(1);
       
   879 }
       
   880 
       
   881 /** 
       
   882  * xmlSecGetQName:
       
   883  * @node:		the context node.
       
   884  * @href:		the QName href (can be NULL).
       
   885  * @local:		the QName local part.
       
   886  *
       
   887  * Creates QName (prefix:local) from @href and @local in the context of the @node.
       
   888  * Caller is responsible for freeing returned string with xmlFree.
       
   889  *
       
   890  * Returns qname or NULL if an error occurs.
       
   891  */
       
   892 EXPORT_C
       
   893 xmlChar* 
       
   894 xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) {
       
   895     xmlChar* qname;
       
   896     xmlNsPtr ns;
       
   897 
       
   898     xmlSecAssert2(node != NULL, NULL);
       
   899     xmlSecAssert2(local != NULL, NULL);
       
   900 
       
   901     /* we don't want to create namespace node ourselves because
       
   902      * it might cause collisions */
       
   903     ns = xmlSearchNsByHref(node->doc, node, href);
       
   904     if((ns == NULL) && (href != NULL)) {
       
   905         xmlSecError(XMLSEC_ERRORS_HERE,
       
   906 		    NULL,
       
   907 		    "xmlSearchNsByHref",
       
   908 	    	    XMLSEC_ERRORS_R_XML_FAILED,
       
   909 		    "node=%s,href=%s",
       
   910     		    xmlSecErrorsSafeString(node->name),
       
   911     		    xmlSecErrorsSafeString(href));
       
   912         return(NULL);
       
   913     }
       
   914         
       
   915     if((ns != NULL) && (ns->prefix != NULL)) {
       
   916 	xmlSecSize len;
       
   917 	
       
   918         len = xmlStrlen(local) + xmlStrlen(ns->prefix) + 4;
       
   919         qname = xmlMalloc(len);
       
   920         if(qname == NULL) {
       
   921   	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   922 		        NULL,
       
   923 		        "xmlMalloc",
       
   924 	    	        XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   925 		        "node=%s",
       
   926 		        xmlSecErrorsSafeString(node->name));
       
   927             return(NULL);
       
   928         }
       
   929         xmlSecStrPrintf(qname, len, BAD_CAST "%s:%s", ns->prefix, local);
       
   930     } else {
       
   931         qname = xmlStrdup(local);
       
   932         if(qname == NULL) {
       
   933   	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   934 		        NULL,
       
   935 		        "xmlStrdup",
       
   936 	    	        XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   937 		        "node=%s",
       
   938 		        xmlSecErrorsSafeString(node->name));
       
   939             return(NULL);
       
   940         }
       
   941     }
       
   942 
       
   943 
       
   944     return(qname);
       
   945 }
       
   946 
       
   947 
       
   948 /*************************************************************************
       
   949  *
       
   950  * QName <-> Integer mapping
       
   951  *
       
   952  ************************************************************************/
       
   953 /** 
       
   954  * xmlSecQName2IntegerGetInfo:
       
   955  * @info:               the qname<->integer mapping information.
       
   956  * @intValue:           the integer value.
       
   957  *
       
   958  * Maps integer @intValue to a QName prefix.
       
   959  * 
       
   960  * Returns the QName info that is mapped to @intValue or NULL if such value
       
   961  * is not found.
       
   962  */
       
   963 EXPORT_C
       
   964 xmlSecQName2IntegerInfoConstPtr 
       
   965 xmlSecQName2IntegerGetInfo(xmlSecQName2IntegerInfoConstPtr info, int intValue) {
       
   966     unsigned int ii;
       
   967 
       
   968     xmlSecAssert2(info != NULL, NULL);
       
   969 
       
   970     for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
       
   971         if(info[ii].intValue == intValue) {
       
   972             return(&info[ii]);
       
   973         }
       
   974     }
       
   975 
       
   976     return(NULL);
       
   977 }
       
   978 
       
   979 /** 
       
   980  * xmlSecQName2IntegerGetInteger:
       
   981  * @info:               the qname<->integer mapping information.
       
   982  * @qnameHref:          the qname href value.
       
   983  * @qnameLocalPart:     the qname local part value.
       
   984  * @intValue:           the pointer to result integer value.
       
   985  * 
       
   986  * Maps qname qname to an integer and returns it in @intValue.
       
   987  * 
       
   988  * Returns 0 on success or a negative value if an error occurs,
       
   989  */
       
   990 EXPORT_C
       
   991 int 
       
   992 xmlSecQName2IntegerGetInteger(xmlSecQName2IntegerInfoConstPtr info, 
       
   993                              const xmlChar* qnameHref, const xmlChar* qnameLocalPart, 
       
   994                              int* intValue) {
       
   995     unsigned int ii;
       
   996 
       
   997     xmlSecAssert2(info != NULL, -1);
       
   998     xmlSecAssert2(qnameLocalPart != NULL, -1);
       
   999     xmlSecAssert2(intValue != NULL, -1);
       
  1000 
       
  1001     for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
       
  1002         if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) && 
       
  1003            xmlStrEqual(info[ii].qnameHref, qnameHref)) {
       
  1004             (*intValue) = info[ii].intValue;
       
  1005             return(0);
       
  1006         }
       
  1007     }
       
  1008 
       
  1009     return(-1);
       
  1010 }
       
  1011 
       
  1012 /** 
       
  1013  * xmlSecQName2IntegerGetIntegerFromInteger:
       
  1014  * @info:               the qname<->integer mapping information.
       
  1015  * @node:               the pointer to node.
       
  1016  * @qname:              the qname string.
       
  1017  * @intValue:           the pointer to result integer value.
       
  1018  * 
       
  1019  * Converts @qname into integer in context of @node.
       
  1020  * 
       
  1021  * Returns 0 on success or a negative value if an error occurs,
       
  1022  */
       
  1023 EXPORT_C
       
  1024 int 
       
  1025 xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info,
       
  1026 					xmlNodePtr node, const xmlChar* qname,
       
  1027                                         int* intValue) {
       
  1028     const xmlChar* qnameLocalPart = NULL;
       
  1029     xmlChar* qnamePrefix = NULL;
       
  1030     const xmlChar* qnameHref;
       
  1031     xmlNsPtr ns;
       
  1032     int ret;
       
  1033     
       
  1034     xmlSecAssert2(info != NULL, -1);
       
  1035     xmlSecAssert2(node != NULL, -1);
       
  1036     xmlSecAssert2(qname != NULL, -1);
       
  1037     xmlSecAssert2(intValue != NULL, -1);
       
  1038     
       
  1039     qnameLocalPart = xmlStrchr(qname, ':');
       
  1040     if(qnameLocalPart != NULL) {
       
  1041         qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
       
  1042         if(qnamePrefix == NULL) {
       
  1043 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1044 		        NULL,
       
  1045 		        "xmlStrndup",
       
  1046 	    	        XMLSEC_ERRORS_R_MALLOC_FAILED,
       
  1047 		        "node=%s,value=%s",
       
  1048 		        xmlSecErrorsSafeString(node->name),
       
  1049                         xmlSecErrorsSafeString(qname));
       
  1050 	    return(-1);	
       
  1051         }
       
  1052         qnameLocalPart++;
       
  1053     } else {
       
  1054         qnamePrefix = NULL;
       
  1055         qnameLocalPart = qname;
       
  1056     }
       
  1057     
       
  1058     /* search namespace href */
       
  1059     ns = xmlSearchNs(node->doc, node, qnamePrefix);
       
  1060     if((ns == NULL) && (qnamePrefix != NULL)) {
       
  1061 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1062 		    NULL,
       
  1063 		    "xmlSearchNs",
       
  1064 	    	    XMLSEC_ERRORS_R_XML_FAILED,
       
  1065 		    "node=%s,qnamePrefix=%s",
       
  1066 		    xmlSecErrorsSafeString(node->name),
       
  1067                     xmlSecErrorsSafeString(qnamePrefix));
       
  1068         if(qnamePrefix != NULL) {
       
  1069             xmlFree(qnamePrefix);
       
  1070         }
       
  1071 	return(-1);	
       
  1072     }
       
  1073     qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
       
  1074 
       
  1075     /* and finally search for integer */
       
  1076     ret = xmlSecQName2IntegerGetInteger(info, qnameHref, qnameLocalPart, intValue);
       
  1077     if(ret < 0) {
       
  1078 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1079 		    NULL,
       
  1080 		    "xmlSecQName2IntegerGetInteger",
       
  1081 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1082 		    "node=%s,qnameLocalPart=%s,qnameHref=%s",
       
  1083 		    xmlSecErrorsSafeString(node->name),
       
  1084                     xmlSecErrorsSafeString(qnameLocalPart),
       
  1085                     xmlSecErrorsSafeString(qnameHref));
       
  1086         if(qnamePrefix != NULL) {
       
  1087             xmlFree(qnamePrefix);
       
  1088         }
       
  1089 	return(-1);	
       
  1090     }
       
  1091 
       
  1092     if(qnamePrefix != NULL) {
       
  1093         xmlFree(qnamePrefix);
       
  1094     }
       
  1095     return(0);
       
  1096 }
       
  1097 
       
  1098 
       
  1099 /** 
       
  1100  * xmlSecQName2IntegerGetStringFromInteger:
       
  1101  * @info:               the qname<->integer mapping information.
       
  1102  * @node:               the pointer to node.
       
  1103  * @intValue:           the integer value.
       
  1104  * 
       
  1105  * Creates qname string for @intValue in context of given @node. Caller
       
  1106  * is responsible for freeing returned string with @xmlFree.
       
  1107  * 
       
  1108  * Returns pointer to newly allocated string on success or NULL if an error occurs,
       
  1109  */
       
  1110 EXPORT_C
       
  1111 xmlChar* 
       
  1112 xmlSecQName2IntegerGetStringFromInteger(xmlSecQName2IntegerInfoConstPtr info,
       
  1113 					xmlNodePtr node, int intValue) {
       
  1114     xmlSecQName2IntegerInfoConstPtr qnameInfo;
       
  1115 
       
  1116     xmlSecAssert2(info != NULL, NULL);
       
  1117     xmlSecAssert2(node != NULL, NULL);
       
  1118 
       
  1119     qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
       
  1120     if(qnameInfo == NULL) {
       
  1121 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1122 		    NULL,
       
  1123 		    "xmlSecQName2IntegerGetInfo",
       
  1124 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1125 		    "node=%s,intValue=%d",
       
  1126 		    xmlSecErrorsSafeString(node->name),
       
  1127                     intValue);
       
  1128         return(NULL);
       
  1129     }
       
  1130     
       
  1131     return (xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart));
       
  1132 }
       
  1133 
       
  1134 /** 
       
  1135  * xmlSecQName2IntegerNodeRead:
       
  1136  * @info:               the qname<->integer mapping information.
       
  1137  * @node:               the pointer to node.
       
  1138  * @intValue:           the pointer to result integer value.
       
  1139  * 
       
  1140  * Reads the content of @node and converts it to an integer using mapping 
       
  1141  * from @info.
       
  1142  * 
       
  1143  * Returns 0 on success or a negative value if an error occurs,
       
  1144  */
       
  1145 EXPORT_C
       
  1146 int 
       
  1147 xmlSecQName2IntegerNodeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, int* intValue) {
       
  1148     xmlChar* content = NULL;
       
  1149     int ret;
       
  1150 
       
  1151     xmlSecAssert2(info != NULL, -1);
       
  1152     xmlSecAssert2(node != NULL, -1);
       
  1153     xmlSecAssert2(intValue != NULL, -1);
       
  1154 
       
  1155     content = xmlNodeGetContent(node);
       
  1156     if(content == NULL) {
       
  1157 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1158 		    NULL,
       
  1159 		    "xmlNodeGetContent",
       
  1160 	    	    XMLSEC_ERRORS_R_XML_FAILED,
       
  1161 		    "node=%s",
       
  1162 		    xmlSecErrorsSafeString(node->name));
       
  1163 	return(-1);	
       
  1164     }
       
  1165 
       
  1166     ret = xmlSecQName2IntegerGetIntegerFromString(info, node, content, intValue);
       
  1167     if(ret < 0) {
       
  1168 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1169 		    NULL,
       
  1170 		    "xmlSecQName2IntegerGetIntegerFromString",
       
  1171 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1172 		    "node=%s,value=%s",
       
  1173 		    xmlSecErrorsSafeString(node->name),
       
  1174                     xmlSecErrorsSafeString(content));
       
  1175         xmlFree(content);
       
  1176 	return(-1);	
       
  1177     }
       
  1178 
       
  1179     xmlFree(content);
       
  1180     return(0);
       
  1181 }
       
  1182 
       
  1183 /** 
       
  1184  * xmlSecQName2IntegerNodeWrite:
       
  1185  * @info:               the qname<->integer mapping information.
       
  1186  * @node:               the parent node.
       
  1187  * @nodeName:           the child node name.
       
  1188  * @nodeNs:             the child node namespace.
       
  1189  * @intValue:           the integer value.
       
  1190  * 
       
  1191  * Creates new child node in @node and sets its value to @intValue.
       
  1192  * 
       
  1193  * Returns 0 on success or a negative value if an error occurs,
       
  1194  */
       
  1195 EXPORT_C
       
  1196 int 
       
  1197 xmlSecQName2IntegerNodeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
       
  1198 			    const xmlChar* nodeName, const xmlChar* nodeNs, int intValue) {
       
  1199     xmlNodePtr cur;
       
  1200     xmlChar* qname = NULL;
       
  1201 
       
  1202     xmlSecAssert2(info != NULL, -1);
       
  1203     xmlSecAssert2(node != NULL, -1);
       
  1204     xmlSecAssert2(nodeName != NULL, -1);
       
  1205 
       
  1206     /* find and build qname */
       
  1207     qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue);
       
  1208     if(qname == NULL) {
       
  1209 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1210 		    NULL,
       
  1211 		    "xmlSecQName2IntegerGetStringFromInteger",
       
  1212 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1213 		    "node=%s,intValue=%d",
       
  1214 		    xmlSecErrorsSafeString(node->name),
       
  1215                     intValue);
       
  1216         return(-1);
       
  1217     }
       
  1218     
       
  1219     cur = xmlSecAddChild(node, nodeName, nodeNs);
       
  1220     if(cur == NULL) {
       
  1221 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1222 		    NULL,
       
  1223 		    "xmlSecAddChild",
       
  1224 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1225 		    "node=%s,intValue=%d",
       
  1226 		    xmlSecErrorsSafeString(nodeName),
       
  1227                     intValue);
       
  1228         xmlFree(qname);
       
  1229         return(-1);
       
  1230     }
       
  1231 
       
  1232     xmlNodeSetContent(cur, qname);
       
  1233     xmlFree(qname);
       
  1234     return(0);
       
  1235 }
       
  1236 
       
  1237 /** 
       
  1238  * xmlSecQName2IntegerAttributeRead:
       
  1239  * @info:               the qname<->integer mapping information.
       
  1240  * @node:               the element node. 
       
  1241  * @attrName:           the attribute name.
       
  1242  * @intValue:           the pointer to result integer value.
       
  1243  * 
       
  1244  * Gets the value of @attrName atrtibute from @node and converts it to integer
       
  1245  * according to @info.
       
  1246  * 
       
  1247  * Returns 0 on success or a negative value if an error occurs,
       
  1248  */
       
  1249 EXPORT_C
       
  1250 int 
       
  1251 xmlSecQName2IntegerAttributeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
       
  1252 			    const xmlChar* attrName, int* intValue) {
       
  1253     xmlChar* attrValue;
       
  1254     int ret;
       
  1255 
       
  1256     xmlSecAssert2(info != NULL, -1);
       
  1257     xmlSecAssert2(node != NULL, -1);
       
  1258     xmlSecAssert2(attrName != NULL, -1);
       
  1259     xmlSecAssert2(intValue != NULL, -1);
       
  1260 
       
  1261     attrValue = xmlGetProp(node, attrName);
       
  1262     if(attrValue == NULL) {
       
  1263 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1264 		    NULL,
       
  1265 		    "xmlGetProp",
       
  1266 	    	    XMLSEC_ERRORS_R_XML_FAILED,
       
  1267 		    "node=%s,attrValue=%s",
       
  1268 		    xmlSecErrorsSafeString(node->name),
       
  1269                     xmlSecErrorsSafeString(attrName));
       
  1270 	return(-1);	
       
  1271     }
       
  1272 
       
  1273     ret = xmlSecQName2IntegerGetIntegerFromString(info, node, attrValue, intValue);
       
  1274     if(ret < 0) {
       
  1275 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1276 		    NULL,
       
  1277 		    "xmlSecQName2IntegerGetIntegerFromString",
       
  1278 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1279 		    "node=%s,attrName=%s,attrValue=%s",
       
  1280 		    xmlSecErrorsSafeString(node->name),
       
  1281                     xmlSecErrorsSafeString(attrName),
       
  1282                     xmlSecErrorsSafeString(attrValue));
       
  1283         xmlFree(attrValue);
       
  1284 	return(-1);	
       
  1285     }
       
  1286 
       
  1287     xmlFree(attrValue);
       
  1288     return(0);
       
  1289 }
       
  1290 
       
  1291 /** 
       
  1292  * xmlSecQName2IntegerAttributeWrite:
       
  1293  * @info:               the qname<->integer mapping information.
       
  1294  * @node:               the parent node.
       
  1295  * @attrName:           the name of attribute.
       
  1296  * @intValue:           the integer value.
       
  1297  * 
       
  1298  * Converts @intValue to a qname and sets it to the value of 
       
  1299  * attribute @attrName in @node.
       
  1300  * 
       
  1301  * Returns 0 on success or a negative value if an error occurs,
       
  1302  */
       
  1303 EXPORT_C
       
  1304 int
       
  1305 xmlSecQName2IntegerAttributeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
       
  1306                             const xmlChar* attrName, int intValue) {
       
  1307     xmlChar* qname;
       
  1308     xmlAttrPtr attr;
       
  1309 
       
  1310     xmlSecAssert2(info != NULL, -1);
       
  1311     xmlSecAssert2(node != NULL, -1);
       
  1312     xmlSecAssert2(attrName != NULL, -1);
       
  1313 
       
  1314     /* find and build qname */
       
  1315     qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue);
       
  1316     if(qname == NULL) {
       
  1317 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1318 		    NULL,
       
  1319 		    "xmlSecQName2IntegerGetStringFromInteger",
       
  1320 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1321 		    "node=%s,attrName=%s,intValue=%d",
       
  1322 		    xmlSecErrorsSafeString(node->name),
       
  1323 		    xmlSecErrorsSafeString(attrName),
       
  1324                     intValue);
       
  1325         return(-1);
       
  1326     }
       
  1327 
       
  1328     attr = xmlSetProp(node, attrName, qname);
       
  1329     if(attr == NULL) {
       
  1330 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1331 		    NULL,
       
  1332 		    "xmlSecAddChildNode",
       
  1333 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1334 		    "node=%s,attrName=%s,intValue=%d",
       
  1335 		    xmlSecErrorsSafeString(node->name),
       
  1336 		    xmlSecErrorsSafeString(attrName),
       
  1337                     intValue);
       
  1338         xmlFree(qname);
       
  1339         return(-1);
       
  1340     }
       
  1341 
       
  1342     xmlFree(qname);
       
  1343     return(0);
       
  1344 }
       
  1345 
       
  1346 /** 
       
  1347  * xmlSecQName2IntegerDebugDump:
       
  1348  * @info:               the qname<->integer mapping information.
       
  1349  * @intValue:           the integer value.
       
  1350  * @output:             the pointer to output FILE.
       
  1351  * 
       
  1352  * Prints @intValue into @output.
       
  1353  */
       
  1354 EXPORT_C
       
  1355 void 
       
  1356 xmlSecQName2IntegerDebugDump(xmlSecQName2IntegerInfoConstPtr info, int intValue,
       
  1357                             const xmlChar* name, FILE* output) {
       
  1358     xmlSecQName2IntegerInfoConstPtr qnameInfo;
       
  1359 
       
  1360     xmlSecAssert(info != NULL);
       
  1361     xmlSecAssert(name != NULL);
       
  1362     xmlSecAssert(output != NULL);
       
  1363 
       
  1364     qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
       
  1365     if(qnameInfo != NULL) {
       
  1366         fprintf(output, "== %s: %d (name=\"%s\", href=\"%s\")\n", name, intValue, 
       
  1367             (qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL,
       
  1368             (qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL);
       
  1369     }    
       
  1370 }
       
  1371 
       
  1372 /** 
       
  1373  * xmlSecQName2IntegerDebugXmlDump:
       
  1374  * @info:               the qname<->integer mapping information.
       
  1375  * @intValue:           the integer value.
       
  1376  * @output:             the pointer to output FILE.
       
  1377  * 
       
  1378  * Prints @intValue into @output in XML format. 
       
  1379  */
       
  1380 EXPORT_C
       
  1381 void 
       
  1382 xmlSecQName2IntegerDebugXmlDump(xmlSecQName2IntegerInfoConstPtr info, int intValue,
       
  1383 			    const xmlChar* name, FILE* output) {
       
  1384     xmlSecQName2IntegerInfoConstPtr qnameInfo;
       
  1385 
       
  1386     xmlSecAssert(info != NULL);
       
  1387     xmlSecAssert(name != NULL);
       
  1388     xmlSecAssert(output != NULL);
       
  1389 
       
  1390     qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
       
  1391     if(qnameInfo != NULL) {
       
  1392         fprintf(output, "<%s value=\"%d\" href=\"%s\">%s<%s>\n", name, intValue, 
       
  1393             (qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL,
       
  1394             (qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL,
       
  1395             name);
       
  1396     }    
       
  1397 }
       
  1398 								 
       
  1399 
       
  1400 /*************************************************************************
       
  1401  *
       
  1402  * QName <-> Bits mask mapping
       
  1403  *
       
  1404  ************************************************************************/
       
  1405 /** 
       
  1406  * xmlSecQName2BitMaskGetInfo:
       
  1407  * @info:               the qname<->bit mask mapping information.
       
  1408  * @mask:               the bit mask.
       
  1409  * 
       
  1410  * Converts @mask to qname.
       
  1411  *
       
  1412  * Returns pointer to the qname info for @mask or NULL if mask is unknown.
       
  1413  */
       
  1414 EXPORT_C
       
  1415 xmlSecQName2BitMaskInfoConstPtr
       
  1416 xmlSecQName2BitMaskGetInfo(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask) {
       
  1417     unsigned int ii;
       
  1418 
       
  1419     xmlSecAssert2(info != NULL, NULL);
       
  1420 
       
  1421     for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
       
  1422         xmlSecAssert2(info[ii].mask != 0, NULL);
       
  1423         if(info[ii].mask == mask) {
       
  1424             return(&info[ii]);
       
  1425         }
       
  1426     }
       
  1427 
       
  1428     return(NULL);
       
  1429 }
       
  1430 
       
  1431 /** 
       
  1432  * xmlSecQName2BitMaskGetBitMask:
       
  1433  * @info:               the qname<->bit mask mapping information.
       
  1434  * @qnameHref:          the qname Href value.
       
  1435  * @qnameLocalPart:     the qname LocalPart value.
       
  1436  * @mask:               the pointer to result mask.
       
  1437  * 
       
  1438  * Converts @qnameLocalPart to @mask.
       
  1439  * 
       
  1440  * Returns 0 on success or a negative value if an error occurs,
       
  1441  */
       
  1442 EXPORT_C
       
  1443 int 
       
  1444 xmlSecQName2BitMaskGetBitMask(xmlSecQName2BitMaskInfoConstPtr info, 
       
  1445                             const xmlChar* qnameHref, const xmlChar* qnameLocalPart,
       
  1446 			    xmlSecBitMask* mask) {
       
  1447     unsigned int ii;
       
  1448 
       
  1449     xmlSecAssert2(info != NULL, -1);
       
  1450     xmlSecAssert2(qnameLocalPart != NULL, -1);
       
  1451     xmlSecAssert2(mask != NULL, -1);
       
  1452 
       
  1453     for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
       
  1454         xmlSecAssert2(info[ii].mask != 0, -1);
       
  1455         if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) && 
       
  1456            xmlStrEqual(info[ii].qnameHref, qnameHref)) {
       
  1457 
       
  1458             (*mask) = info[ii].mask;
       
  1459             return(0);
       
  1460         }
       
  1461     }
       
  1462 
       
  1463     return(-1);
       
  1464 }
       
  1465 
       
  1466 /** 
       
  1467  * xmlSecQName2BitMaskGetBitMaskFromBitMask:
       
  1468  * @info:               the qname<->integer mapping information.
       
  1469  * @node:               the pointer to node.
       
  1470  * @qname:              the qname string.
       
  1471  * @mask:               the pointer to result msk value.
       
  1472  * 
       
  1473  * Converts @qname into integer in context of @node.
       
  1474  * 
       
  1475  * Returns 0 on success or a negative value if an error occurs,
       
  1476  */
       
  1477 EXPORT_C
       
  1478 int 
       
  1479 xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info,
       
  1480 					xmlNodePtr node, const xmlChar* qname,
       
  1481                                         xmlSecBitMask* mask) {
       
  1482     const xmlChar* qnameLocalPart = NULL;
       
  1483     xmlChar* qnamePrefix = NULL;
       
  1484     const xmlChar* qnameHref;
       
  1485     xmlNsPtr ns;
       
  1486     int ret;
       
  1487     
       
  1488     xmlSecAssert2(info != NULL, -1);
       
  1489     xmlSecAssert2(node != NULL, -1);
       
  1490     xmlSecAssert2(qname != NULL, -1);
       
  1491     xmlSecAssert2(mask != NULL, -1);
       
  1492 
       
  1493     qnameLocalPart = xmlStrchr(qname, ':');
       
  1494     if(qnameLocalPart != NULL) {
       
  1495         qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
       
  1496         if(qnamePrefix == NULL) {
       
  1497 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1498 		        NULL,
       
  1499 		        "xmlStrndup",
       
  1500 	    	        XMLSEC_ERRORS_R_MALLOC_FAILED,
       
  1501 		        "node=%s,value=%s",
       
  1502 		        xmlSecErrorsSafeString(node->name),
       
  1503                         xmlSecErrorsSafeString(qname));
       
  1504 	    return(-1);	
       
  1505         }
       
  1506         qnameLocalPart++;
       
  1507     } else {
       
  1508         qnamePrefix = NULL;
       
  1509         qnameLocalPart = qname;
       
  1510     }
       
  1511     
       
  1512     /* search namespace href */
       
  1513     ns = xmlSearchNs(node->doc, node, qnamePrefix);
       
  1514     if((ns == NULL) && (qnamePrefix != NULL)) {
       
  1515 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1516 		    NULL,
       
  1517 		    "xmlSearchNs",
       
  1518 	    	    XMLSEC_ERRORS_R_XML_FAILED,
       
  1519 		    "node=%s,qnamePrefix=%s",
       
  1520 		    xmlSecErrorsSafeString(node->name),
       
  1521                     xmlSecErrorsSafeString(qnamePrefix));
       
  1522         if(qnamePrefix != NULL) {
       
  1523             xmlFree(qnamePrefix);
       
  1524         }
       
  1525 	return(-1);	
       
  1526     }
       
  1527     qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
       
  1528 
       
  1529     /* and finally search for integer */
       
  1530     ret = xmlSecQName2BitMaskGetBitMask(info, qnameHref, qnameLocalPart, mask);
       
  1531     if(ret < 0) {
       
  1532 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1533 		    NULL,
       
  1534 		    "xmlSecQName2BitMaskGetBitMask",
       
  1535 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1536 		    "node=%s,qnameLocalPart=%s,qnameHref=%s",
       
  1537 		    xmlSecErrorsSafeString(node->name),
       
  1538                     xmlSecErrorsSafeString(qnameLocalPart),
       
  1539                     xmlSecErrorsSafeString(qnameHref));
       
  1540         if(qnamePrefix != NULL) {
       
  1541             xmlFree(qnamePrefix);
       
  1542         }
       
  1543 	return(-1);	
       
  1544     }
       
  1545 
       
  1546     if(qnamePrefix != NULL) {
       
  1547         xmlFree(qnamePrefix);
       
  1548     }
       
  1549     return(0);
       
  1550 }
       
  1551 
       
  1552 
       
  1553 /** 
       
  1554  * xmlSecQName2BitMaskGetStringFromBitMask:
       
  1555  * @info:               the qname<->integer mapping information.
       
  1556  * @node:               the pointer to node.
       
  1557  * @mask:               the mask.
       
  1558  * 
       
  1559  * Creates qname string for @mask in context of given @node. Caller
       
  1560  * is responsible for freeing returned string with @xmlFree.
       
  1561  * 
       
  1562  * Returns pointer to newly allocated string on success or NULL if an error occurs,
       
  1563  */
       
  1564 EXPORT_C
       
  1565 xmlChar* 
       
  1566 xmlSecQName2BitMaskGetStringFromBitMask(xmlSecQName2BitMaskInfoConstPtr info,
       
  1567 					xmlNodePtr node, xmlSecBitMask mask) {
       
  1568     xmlSecQName2BitMaskInfoConstPtr qnameInfo;
       
  1569 
       
  1570     xmlSecAssert2(info != NULL, NULL);
       
  1571     xmlSecAssert2(node != NULL, NULL);
       
  1572 
       
  1573     qnameInfo = xmlSecQName2BitMaskGetInfo(info, mask);
       
  1574     if(qnameInfo == NULL) {
       
  1575 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1576 		    NULL,
       
  1577 		    "xmlSecQName2BitMaskGetInfo",
       
  1578 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1579 		    "node=%s,mask=%d",
       
  1580 		    xmlSecErrorsSafeString(node->name),
       
  1581                     mask);
       
  1582         return(NULL);
       
  1583     }
       
  1584     
       
  1585     return(xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart));
       
  1586 }
       
  1587 
       
  1588 /** 
       
  1589  * xmlSecQName2BitMaskNodesRead:
       
  1590  * @info:               the qname<->bit mask mapping information.
       
  1591  * @node:               the start.
       
  1592  * @nodeName:           the mask nodes name.
       
  1593  * @nodeNs:             the mask nodes namespace.
       
  1594  * @stopOnUnknown:	if this flag is set then function exits if unknown
       
  1595  *			value was found.
       
  1596  * @mask:               the pointer to result mask.
       
  1597  * 
       
  1598  * Reads <@nodeNs:@nodeName> elements and puts the result bit mask
       
  1599  * into @mask. When function exits, @node points to the first element node
       
  1600  * after all the <@nodeNs:@nodeName> elements.
       
  1601  * 
       
  1602  * Returns 0 on success or a negative value if an error occurs,
       
  1603  */
       
  1604 EXPORT_C
       
  1605 int 
       
  1606 xmlSecQName2BitMaskNodesRead(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr* node,
       
  1607 			    const xmlChar* nodeName, const xmlChar* nodeNs, 
       
  1608                             int stopOnUnknown, xmlSecBitMask* mask) {
       
  1609     xmlNodePtr cur;
       
  1610     xmlChar* content;
       
  1611     xmlSecBitMask tmp;
       
  1612     int ret;
       
  1613 
       
  1614     xmlSecAssert2(info != NULL, -1);
       
  1615     xmlSecAssert2(node != NULL, -1);
       
  1616     xmlSecAssert2(mask != NULL, -1);
       
  1617 
       
  1618     (*mask) = 0;
       
  1619     cur = (*node);
       
  1620     while((cur != NULL) && (xmlSecCheckNodeName(cur, nodeName, nodeNs))) {
       
  1621         content = xmlNodeGetContent(cur);
       
  1622         if(content == NULL) {
       
  1623 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1624 		        NULL,
       
  1625 		        "xmlNodeGetContent",
       
  1626 	    	        XMLSEC_ERRORS_R_XML_FAILED,
       
  1627 		        "node=%s",
       
  1628 		        xmlSecErrorsSafeString(cur->name));
       
  1629 	    return(-1);	
       
  1630         }
       
  1631         
       
  1632         ret = xmlSecQName2BitMaskGetBitMaskFromString(info, cur, content, &tmp);
       
  1633         if(ret < 0) {
       
  1634 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1635 		        NULL,
       
  1636 		        "xmlSecQName2BitMaskGetBitMaskFromString",
       
  1637 	    	        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1638 		        "value=%s",
       
  1639 		        xmlSecErrorsSafeString(content));
       
  1640             xmlFree(content);
       
  1641 	    return(-1);	
       
  1642         }
       
  1643         xmlFree(content);
       
  1644 
       
  1645 	if((stopOnUnknown != 0) && (tmp == 0)) {
       
  1646 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1647 		        NULL,
       
  1648 		        "xmlSecQName2BitMaskGetBitMaskFromString",
       
  1649 	    	        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1650 		        "value=%s",
       
  1651 		        xmlSecErrorsSafeString(content));
       
  1652 	    return(-1);	
       
  1653 	}
       
  1654 	
       
  1655         (*mask) |= tmp;
       
  1656 	cur = xmlSecGetNextElementNode(cur->next);
       
  1657     }
       
  1658 
       
  1659     (*node) = cur;    
       
  1660     return(0); 
       
  1661 }
       
  1662 
       
  1663 /** 
       
  1664  * xmlSecQName2BitMaskNodesWrite:
       
  1665  * @info:               the qname<->bit mask mapping information.
       
  1666  * @node:               the parent element for mask nodes.
       
  1667  * @nodeName:           the mask nodes name.
       
  1668  * @nodeNs:             the mask nodes namespace.
       
  1669  * @mask:               the bit mask.
       
  1670  * 
       
  1671  * Writes <@nodeNs:@nodeName> elemnts with values from @mask to @node.
       
  1672  * 
       
  1673  * Returns 0 on success or a negative value if an error occurs,
       
  1674  */
       
  1675 EXPORT_C
       
  1676 int 
       
  1677 xmlSecQName2BitMaskNodesWrite(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr node,
       
  1678 			    const xmlChar* nodeName, const xmlChar* nodeNs, 
       
  1679                             xmlSecBitMask mask) {
       
  1680     unsigned int ii;
       
  1681 
       
  1682     xmlSecAssert2(info != NULL, -1);
       
  1683     xmlSecAssert2(node != NULL, -1);
       
  1684     xmlSecAssert2(nodeName != NULL, -1);
       
  1685 
       
  1686     for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
       
  1687         xmlSecAssert2(info[ii].mask != 0, -1);
       
  1688 
       
  1689         if((mask & info[ii].mask) != 0) {
       
  1690             xmlNodePtr cur;
       
  1691             xmlChar* qname;
       
  1692             
       
  1693 	    qname = xmlSecGetQName(node, info[ii].qnameHref, info[ii].qnameLocalPart);
       
  1694             if(qname == NULL) {
       
  1695 	        xmlSecError(XMLSEC_ERRORS_HERE,
       
  1696 		            NULL,
       
  1697 		            "xmlSecGetQName",
       
  1698 	    	            XMLSEC_ERRORS_R_XML_FAILED,
       
  1699 		            "node=%s",
       
  1700 		            xmlSecErrorsSafeString(nodeName));
       
  1701 	        return(-1);	
       
  1702             }
       
  1703             
       
  1704             cur = xmlSecAddChild(node, nodeName, nodeNs);
       
  1705             if(cur == NULL) {
       
  1706 	        xmlSecError(XMLSEC_ERRORS_HERE,
       
  1707 		            NULL,
       
  1708 		            "xmlSecAddChild",
       
  1709 	    	            XMLSEC_ERRORS_R_XML_FAILED,
       
  1710 		            "node=%s",
       
  1711 		            xmlSecErrorsSafeString(nodeName));
       
  1712                 xmlFree(qname);
       
  1713 	        return(-1);
       
  1714             }
       
  1715             
       
  1716             xmlNodeSetContent(cur, qname);
       
  1717             xmlFree(qname);
       
  1718         }
       
  1719     }
       
  1720     return(0);
       
  1721 }
       
  1722 
       
  1723 /** 
       
  1724  * xmlSecQName2BitMaskDebugDump:
       
  1725  * @info:               the qname<->bit mask mapping information.
       
  1726  * @mask:               the bit mask.
       
  1727  * @output:             the pointer to output FILE.
       
  1728  * 
       
  1729  * Prints debug information about @mask to @output.
       
  1730  */
       
  1731 EXPORT_C
       
  1732 void 
       
  1733 xmlSecQName2BitMaskDebugDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask,
       
  1734 			    const xmlChar* name, FILE* output) {
       
  1735     unsigned int ii;
       
  1736 
       
  1737     xmlSecAssert(info != NULL);
       
  1738     xmlSecAssert(name != NULL);
       
  1739     xmlSecAssert(output != NULL);
       
  1740 
       
  1741     if(mask == 0) {
       
  1742         return;
       
  1743     }
       
  1744 
       
  1745     fprintf(output, "== %s (0x%08x): ", name, mask);
       
  1746     for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
       
  1747         xmlSecAssert(info[ii].mask != 0);
       
  1748 
       
  1749         if((mask & info[ii].mask) != 0) {
       
  1750             fprintf(output, "name=\"%s\" (href=\"%s\"),", info[ii].qnameLocalPart, info[ii].qnameHref);
       
  1751         }
       
  1752     }
       
  1753     fprintf(output, "\n");
       
  1754 }
       
  1755 
       
  1756 /** 
       
  1757  * xmlSecQName2BitMaskDebugXmlDump:
       
  1758  * @info:               the qname<->bit mask mapping information.
       
  1759  * @mask:               the bit mask.
       
  1760  * @output:             the pointer to output FILE.
       
  1761  * 
       
  1762  * Prints debug information about @mask to @output in XML format.
       
  1763  */
       
  1764 EXPORT_C
       
  1765 void 
       
  1766 xmlSecQName2BitMaskDebugXmlDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask,
       
  1767 			    const xmlChar* name, FILE* output) {
       
  1768     unsigned int ii;
       
  1769 
       
  1770     xmlSecAssert(info != NULL);
       
  1771     xmlSecAssert(name != NULL);
       
  1772     xmlSecAssert(output != NULL);
       
  1773 
       
  1774     if(mask == 0) {
       
  1775         return;
       
  1776     }
       
  1777 
       
  1778     fprintf(output, "<%sList>\n", name);
       
  1779     for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
       
  1780         xmlSecAssert(info[ii].mask != 0);
       
  1781 
       
  1782         if((mask & info[ii].mask) != 0) {
       
  1783             fprintf(output, "<%s href=\"%s\">%s</%s>\n", name, 
       
  1784                     info[ii].qnameHref, info[ii].qnameLocalPart, name);
       
  1785         }
       
  1786     }
       
  1787     fprintf(output, "</%sList>\n", name);
       
  1788 }
       
  1789 								 
       
  1790 
       
  1791 
       
  1792