/**
* XML Security Library (http://www.aleksey.com/xmlsec).
*
* Common XML Doc utility functions
*
* This is free software; see Copyright file in the source
* distribution for preciese wording.
*
* Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
* Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
*/
#include "xmlsec_globals.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <libxml2_tree.h>
#include <libxml2_valid.h>
#include <libxml2_xpath.h>
#include <libxml2_xpathinternals.h>
#include <libxml2_globals.h>
#include "xmlsec_xmlsec.h"
#include "xmlsec_xmltree.h"
#include "xmlsec_parser.h"
#include "xmlsec_private.h"
#include "xmlsec_base64.h"
#include "xmlsec_errors.h"
#include "xmlsec_templates.h"
/**
* xmlSecFindChild:
* @parent: the pointer to XML node.
* @name: the name.
* @ns: the namespace href (may be NULL).
*
* Searches a direct child of the @parent node having given name and
* namespace href.
*
* Returns the pointer to the found node or NULL if an error occurs or
* node is not found.
*/
EXPORT_C
xmlNodePtr
xmlSecFindChild(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
xmlNodePtr cur;
xmlSecAssert2(parent != NULL, NULL);
xmlSecAssert2(name != NULL, NULL);
cur = parent->children;
while(cur != NULL) {
if(cur->type == XML_ELEMENT_NODE) {
if(xmlSecCheckNodeName(cur, name, ns)) {
return(cur);
}
}
cur = cur->next;
}
return(NULL);
}
/**
* xmlSecFindParent:
* @cur: the pointer to an XML node.
* @name: the name.
* @ns: the namespace href (may be NULL).
*
* Searches the ancestors axis of the @cur node for a node having given name
* and namespace href.
*
* Returns the pointer to the found node or NULL if an error occurs or
* node is not found.
*/
EXPORT_C
xmlNodePtr
xmlSecFindParent(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
xmlSecAssert2(cur != NULL, NULL);
xmlSecAssert2(name != NULL, NULL);
if(xmlSecCheckNodeName(cur, name, ns)) {
return(cur);
} else if(cur->parent != NULL) {
return(xmlSecFindParent(cur->parent, name, ns));
}
return(NULL);
}
/**
* xmlSecFindNode:
* @parent: the pointer to XML node.
* @name: the name.
* @ns: the namespace href (may be NULL).
*
* Searches all children of the @parent node having given name and
* namespace href.
*
* Returns the pointer to the found node or NULL if an error occurs or
* node is not found.
*/
EXPORT_C
xmlNodePtr
xmlSecFindNode(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
xmlNodePtr cur;
xmlNodePtr ret;
xmlSecAssert2(name != NULL, NULL);
cur = parent;
while(cur != NULL) {
if((cur->type == XML_ELEMENT_NODE) && xmlSecCheckNodeName(cur, name, ns)) {
return(cur);
}
if(cur->children != NULL) {
ret = xmlSecFindNode(cur->children, name, ns);
if(ret != NULL) {
return(ret);
}
}
cur = cur->next;
}
return(NULL);
}
/**
* xmlSecGetNodeNsHref:
* @cur: the pointer to node.
*
* Get's node's namespace href.
*
* Returns node's namespace href.
*/
EXPORT_C
const xmlChar*
xmlSecGetNodeNsHref(const xmlNodePtr cur) {
xmlNsPtr ns;
xmlSecAssert2(cur != NULL, NULL);
/* do we have a namespace in the node? */
if(cur->ns != NULL) {
return(cur->ns->href);
}
/* search for default namespace */
ns = xmlSearchNs(cur->doc, cur, NULL);
if(ns != NULL) {
return(ns->href);
}
return(NULL);
}
/**
* xmlSecCheckNodeName:
* @cur: the pointer to an XML node.
* @name: the name,
* @ns: the namespace href.
*
* Checks that the node has a given name and a given namespace href.
*
* Returns 1 if the node matches or 0 otherwise.
*/
EXPORT_C
int
xmlSecCheckNodeName(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
xmlSecAssert2(cur != NULL, 0);
return(xmlStrEqual(cur->name, name) &&
xmlStrEqual(xmlSecGetNodeNsHref(cur), ns));
}
/**
* xmlSecAddChild:
* @parent: the pointer to an XML node.
* @name: the new node name.
* @ns: the new node namespace.
*
* Adds a child to the node @parent with given @name and namespace @ns.
*
* Returns pointer to the new node or NULL if an error occurs.
*/
EXPORT_C
xmlNodePtr
xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
xmlNodePtr cur;
xmlNodePtr text;
xmlSecAssert2(parent != NULL, NULL);
xmlSecAssert2(name != NULL, NULL);
if(xmlGetNewLineFlag() && parent->children == NULL) {
text = xmlNewText(xmlSecStringCR);
if(text == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewText",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddChild(parent, text);
}
cur = xmlNewChild(parent, NULL, name, NULL);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewChild",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
/* namespaces support */
if(ns != NULL) {
xmlNsPtr nsPtr;
nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
if((nsPtr == NULL) || !xmlStrEqual(nsPtr->href, ns)) {
nsPtr = xmlNewNs(cur, ns, NULL);
}
xmlSetNs(cur, nsPtr);
}
if(xmlGetNewLineFlag())
{
text = xmlNewText(xmlSecStringCR);
if(text == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewText",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddChild(parent, text);
}
return(cur);
}
/**
* xmlSecAddChildNode:
* @parent: the pointer to an XML node.
* @child: the new node.
*
* Adds @child node to the @parent node.
*
* Returns pointer to the new node or NULL if an error occurs.
*/
EXPORT_C
xmlNodePtr
xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) {
xmlNodePtr text;
xmlSecAssert2(parent != NULL, NULL);
xmlSecAssert2(child != NULL, NULL);
if(xmlGetNewLineFlag() && parent->children == NULL) {
text = xmlNewText(xmlSecStringCR);
if(text == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewText",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddChild(parent, text);
}
xmlAddChild(parent, child);
if(xmlGetNewLineFlag())
{
text = xmlNewText(xmlSecStringCR);
if(text == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewText",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddChild(parent, text);
}
return(child);
}
/**
* xmlSecAddNextSibling
* @node: the pointer to an XML node.
* @name: the new node name.
* @ns: the new node namespace.
*
* Adds next sibling to the node @node with given @name and namespace @ns.
*
* Returns pointer to the new node or NULL if an error occurs.
*/
EXPORT_C
xmlNodePtr
xmlSecAddNextSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
xmlNodePtr cur;
xmlNodePtr text;
xmlSecAssert2(node != NULL, NULL);
xmlSecAssert2(name != NULL, NULL);
cur = xmlNewNode(NULL, name);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewNode",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddNextSibling(node, cur);
/* namespaces support */
if(ns != NULL) {
xmlNsPtr nsPtr;
nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
if((nsPtr == NULL) || !xmlStrEqual(nsPtr->href, ns)) {
nsPtr = xmlNewNs(cur, ns, NULL);
}
xmlSetNs(cur, nsPtr);
}
if(xmlGetNewLineFlag())
{
text = xmlNewText(xmlSecStringCR);
if(text == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewText",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddNextSibling(node, text);
}
return(cur);
}
/**
* xmlSecAddPrevSibling
* @node: the pointer to an XML node.
* @name: the new node name.
* @ns: the new node namespace.
*
* Adds prev sibling to the node @node with given @name and namespace @ns.
*
* Returns pointer to the new node or NULL if an error occurs.
*/
EXPORT_C
xmlNodePtr
xmlSecAddPrevSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
xmlNodePtr cur;
xmlNodePtr text;
xmlSecAssert2(node != NULL, NULL);
xmlSecAssert2(name != NULL, NULL);
cur = xmlNewNode(NULL, name);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewNode",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddPrevSibling(node, cur);
/* namespaces support */
if(ns != NULL) {
xmlNsPtr nsPtr;
nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
if((nsPtr == NULL) || !xmlStrEqual(nsPtr->href, ns)) {
nsPtr = xmlNewNs(cur, ns, NULL);
if (nsPtr == NULL)
return(NULL);
}
xmlSetNs(cur, nsPtr);
}
if(xmlGetNewLineFlag())
{
text = xmlNewText(xmlSecStringCR);
if(text == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewText",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlAddPrevSibling(node, text);
}
return(cur);
}
/**
* xmlSecGetNextElementNode:
* @cur: the pointer to an XML node.
*
* Seraches for the next element node.
*
* Returns the pointer to next element node or NULL if it is not found.
*/
EXPORT_C
xmlNodePtr
xmlSecGetNextElementNode(xmlNodePtr cur) {
while((cur != NULL) && (cur->type != XML_ELEMENT_NODE)) {
cur = cur->next;
}
return(cur);
}
/**
* xmlSecReplaceNode:
* @node: the current node.
* @newNode: the new node.
*
* Swaps the @node and @newNode in the XML tree.
*
* Returns 0 on success or a negative value if an error occurs.
*/
EXPORT_C
int
xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode) {
xmlNodePtr oldNode;
int restoreRoot = 0;
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(newNode != NULL, -1);
/* fix documents children if necessary first */
if((node->doc != NULL) && (node->doc->children == node)) {
node->doc->children = node->next;
restoreRoot = 1;
}
if((newNode->doc != NULL) && (newNode->doc->children == newNode)) {
newNode->doc->children = newNode->next;
}
oldNode = xmlReplaceNode(node, newNode);
if(oldNode == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlReplaceNode",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(-1);
}
if(restoreRoot != 0) {
xmlDocSetRootElement(oldNode->doc, newNode);
}
xmlFreeNode(oldNode);
return(0);
}
/**
* xmlSecReplaceContent
* @node: the current node.
* @newNode: the new node.
*
* Swaps the content of @node and @newNode.
*
* Returns 0 on success or a negative value if an error occurs.
*/
EXPORT_C
int
xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode) {
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(newNode != NULL, -1);
xmlUnlinkNode(newNode);
xmlSetTreeDoc(newNode, node->doc);
xmlNodeSetContent(node, NULL);
xmlAddChild(node, newNode);
xmlSetTreeDoc(newNode, node->doc);
return(0);
}
/**
* xmlSecReplaceNodeBuffer:
* @node: the current node.
* @buffer: the XML data.
* @size: the XML data size.
*
* Swaps the @node and the parsed XML data from the @buffer in the XML tree.
*
* Returns 0 on success or a negative value if an error occurs.
*/
EXPORT_C
int
xmlSecReplaceNodeBuffer(xmlNodePtr node,
const xmlSecByte *buffer, xmlSecSize size) {
xmlNodePtr results = NULL;
xmlNodePtr next = NULL;
xmlNodePtr tmp = NULL; // MK added
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(node->parent != NULL, -1);
/* parse buffer in the context of node's parent */
if(xmlParseInNodeContext(node->parent, (const char*)buffer, size, XML_PARSE_NODICT, &results) != XML_ERR_OK) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlParseInNodeContext",
XMLSEC_ERRORS_R_XML_FAILED,
"Failed to parse content");
return(-1);
}
if(results == NULL && node->parent->type == XML_DOCUMENT_NODE)
{
tmp = node->last;
xmlUnlinkNode(tmp);
results = tmp;
}
/* add new nodes */
while (results != NULL) {
next = results->next;
xmlAddPrevSibling(node, results);
results = next;
}
/* remove old node */
xmlUnlinkNode(node);
xmlFreeNode(node);
return(0);
}
/**
* xmlSecAddIDs:
* @doc: the pointer to an XML document.
* @cur: the pointer to an XML node.
* @ids: the pointer to a NULL terminated list of ID attributes.
*
* Walks thru all children of the @cur node and adds all attributes
* from the @ids list to the @doc document IDs attributes hash.
*/
EXPORT_C
void
xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr cur, const xmlChar** ids) {
xmlNodePtr children = NULL;
xmlSecAssert(doc != NULL);
xmlSecAssert(ids != NULL);
if((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
xmlAttrPtr attr;
xmlAttrPtr tmp;
int i;
xmlChar* name;
for(attr = cur->properties; attr != NULL; attr = attr->next) {
for(i = 0; ids[i] != NULL; ++i) {
if(xmlStrEqual(attr->name, ids[i])) {
name = xmlNodeListGetString(doc, attr->children, 1);
if(name != NULL) {
tmp = xmlGetID(doc, name);
if(tmp == NULL) {
xmlAddID(NULL, doc, name, attr);
} else if(tmp != attr) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
NULL,
XMLSEC_ERRORS_R_INVALID_DATA,
"id=%s already defined",
xmlSecErrorsSafeString(name));
}
xmlFree(name);
}
}
}
}
children = cur->children;
} else if(cur == NULL) {
children = doc->children;
}
while(children != NULL) {
if(children->type == XML_ELEMENT_NODE) {
xmlSecAddIDs(doc, children, ids);
}
children = children->next;
}
}
/**
* xmlSecGenerateAndAddID:
* @node: the node to ID attr to.
* @attrName: the ID attr name.
* @prefix: the prefix to add to the generated ID (can be NULL).
* @len: the length of ID.
*
* Generates a unique ID in the format <@prefix>base64-encoded(@len random bytes)
* and puts it in the attribute @attrName.
*
* Returns 0 on success or a negative value if an error occurs.
*/
EXPORT_C
int
xmlSecGenerateAndAddID(xmlNodePtr node, const xmlChar* attrName, const xmlChar* prefix, xmlSecSize len) {
xmlChar* id;
int count;
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(attrName != NULL, -1);
/* we will try 5 times before giving up */
for(count = 0; count < 5; count++) {
id = xmlSecGenerateID(prefix, len);
if(id == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecGenerateID",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(-1);
}
if((node->doc == NULL) || (xmlGetID(node->doc, id) == NULL)) {
/* this is a unique ID in the document and we can use it */
if(xmlSetProp(node, attrName, id) == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSetProp",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
xmlFree(id);
return(-1);
}
xmlFree(id);
return(0);
}
xmlFree(id);
}
return(-1);
}
/**
* xmlSecGenerateID:
* @prefix: the prefix to add to the generated ID (can be NULL).
* @len: the length of ID.
*
* Generates a unique ID in the format <@prefix>base64-encoded(@len random bytes).
* The caller is responsible for freeing returned string using @xmlFree function.
*
* Returns pointer to generated ID string or NULL if an error occurs.
*/
EXPORT_C
xmlChar*
xmlSecGenerateID(const xmlChar* prefix, xmlSecSize len) {
xmlSecBuffer buffer;
xmlSecSize i, binLen;
xmlChar* res;
xmlChar* p;
int ret;
xmlSecAssert2(len > 0, NULL);
/* we will do base64 decoding later */
binLen = (3 * len + 1) / 4;
ret = xmlSecBufferInitialize(&buffer, binLen + 1);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecBufferInitialize",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
xmlSecAssert2(xmlSecBufferGetData(&buffer) != NULL, NULL);
xmlSecAssert2(xmlSecBufferGetMaxSize(&buffer) >= binLen, NULL);
ret = xmlSecBufferSetSize(&buffer, binLen);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecBufferSetSize",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
xmlSecBufferFinalize(&buffer);
return(NULL);
}
xmlSecAssert2(xmlSecBufferGetSize(&buffer) == binLen, NULL);
/* create random bytes */
for(i = 0; i < binLen; i++) {
(xmlSecBufferGetData(&buffer)) [i] = (xmlSecByte) (256.0 * rand() / (RAND_MAX + 1.0));
}
/* base64 encode random bytes */
res = xmlSecBase64Encode(xmlSecBufferGetData(&buffer), xmlSecBufferGetSize(&buffer), 0);
if((res == NULL) || (xmlStrlen(res) == 0)) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecBase64Encode",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
xmlSecBufferFinalize(&buffer);
return(NULL);
}
xmlSecBufferFinalize(&buffer);
/* truncate the generated id attribute if needed */
if(xmlStrlen(res) > (int)len) {
res[len] = '\0';
}
/* we need to cleanup base64 encoded id because ID attr can't have '+' or '/' characters */
for(p = res; (*p) != '\0'; p++) {
if(((*p) == '+') || ((*p) == '/')) {
(*p) = '_';
}
}
/* add prefix if exist */
if(prefix) {
xmlChar* tmp;
xmlSecSize tmpLen;
tmpLen = xmlStrlen(prefix) + xmlStrlen(res) + 1;
tmp = xmlMalloc(tmpLen + 1);
if(tmp == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlMalloc",
XMLSEC_ERRORS_R_MALLOC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
xmlFree(res);
return(NULL);
}
xmlSecStrPrintf(tmp, tmpLen, BAD_CAST "%s%s", prefix, res);
xmlFree(res);
res = tmp;
} else {
/* no prefix: check that ID attribute starts from a letter */
if(!(((res[0] >= 'A') && (res[0] <= 'Z')) ||
((res[0] >= 'a') && (res[0] <= 'z')))) {
res[0] = 'A';
}
}
return(res);
}
/**
* xmlSecCreateTree:
* @rootNodeName: the root node name.
* @rootNodeNs: the root node namespace (otpional).
*
* Creates a new XML tree with one root node @rootNodeName.
*
* Returns pointer to the newly created tree or NULL if an error occurs.
*/
EXPORT_C
xmlDocPtr
xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) {
xmlDocPtr doc;
xmlNodePtr root;
xmlNsPtr ns;
xmlSecAssert2(rootNodeName != NULL, NULL);
/* create doc */
doc = xmlNewDoc(BAD_CAST "1.0");
if(doc == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewDoc",
XMLSEC_ERRORS_R_XML_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
return(NULL);
}
/* create root node */
root = xmlNewDocNode(doc, NULL, rootNodeName, NULL);
if(root == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewDocNode",
XMLSEC_ERRORS_R_XML_FAILED,
"node=Keys");
xmlFreeDoc(doc);
return(NULL);
}
xmlDocSetRootElement(doc, root);
/* and set root node namespace */
ns = xmlNewNs(root, rootNodeNs, NULL);
if(ns == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNewNs",
XMLSEC_ERRORS_R_XML_FAILED,
"ns=%s",
xmlSecErrorsSafeString(rootNodeNs));
xmlFreeDoc(doc);
return(NULL);
}
xmlSetNs(root, ns);
return(doc);
}
/**
* xmlSecIsEmptyNode:
* @node: the node to check
*
* Checks whethere the @node is empty (i.e. has only whitespaces children).
*
* Returns 1 if @node is empty, 0 otherwise or a negative value if an error occurs.
*/
EXPORT_C
int
xmlSecIsEmptyNode(xmlNodePtr node) {
xmlChar* content;
int res;
xmlSecAssert2(node != NULL, -1);
if(xmlSecGetNextElementNode(node->children) != NULL) {
return(0);
}
content = xmlNodeGetContent(node);
if(content == NULL) {
return(1);
}
res = xmlSecIsEmptyString(content);
xmlFree(content);
return(res);
}
/**
* xmlSecIsEmptyString:
* @str: the string to check
*
* Checks whethere the @str is empty (i.e. has only whitespaces children).
*
* Returns 1 if @str is empty, 0 otherwise or a negative value if an error occurs.
*/
EXPORT_C
int
xmlSecIsEmptyString(const xmlChar* str) {
xmlSecAssert2(str != NULL, -1);
for( ;*str != '\0'; ++str) {
if(!isspace((int)(*str))) {
return(0);
}
}
return(1);
}
/**
* xmlSecGetQName:
* @node: the context node.
* @href: the QName href (can be NULL).
* @local: the QName local part.
*
* Creates QName (prefix:local) from @href and @local in the context of the @node.
* Caller is responsible for freeing returned string with xmlFree.
*
* Returns qname or NULL if an error occurs.
*/
EXPORT_C
xmlChar*
xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) {
xmlChar* qname;
xmlNsPtr ns;
xmlSecAssert2(node != NULL, NULL);
xmlSecAssert2(local != NULL, NULL);
/* we don't want to create namespace node ourselves because
* it might cause collisions */
ns = xmlSearchNsByHref(node->doc, node, href);
if((ns == NULL) && (href != NULL)) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSearchNsByHref",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s,href=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(href));
return(NULL);
}
if((ns != NULL) && (ns->prefix != NULL)) {
xmlSecSize len;
len = xmlStrlen(local) + xmlStrlen(ns->prefix) + 4;
qname = xmlMalloc(len);
if(qname == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlMalloc",
XMLSEC_ERRORS_R_MALLOC_FAILED,
"node=%s",
xmlSecErrorsSafeString(node->name));
return(NULL);
}
xmlSecStrPrintf(qname, len, BAD_CAST "%s:%s", ns->prefix, local);
} else {
qname = xmlStrdup(local);
if(qname == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlStrdup",
XMLSEC_ERRORS_R_MALLOC_FAILED,
"node=%s",
xmlSecErrorsSafeString(node->name));
return(NULL);
}
}
return(qname);
}
/*************************************************************************
*
* QName <-> Integer mapping
*
************************************************************************/
/**
* xmlSecQName2IntegerGetInfo:
* @info: the qname<->integer mapping information.
* @intValue: the integer value.
*
* Maps integer @intValue to a QName prefix.
*
* Returns the QName info that is mapped to @intValue or NULL if such value
* is not found.
*/
EXPORT_C
xmlSecQName2IntegerInfoConstPtr
xmlSecQName2IntegerGetInfo(xmlSecQName2IntegerInfoConstPtr info, int intValue) {
unsigned int ii;
xmlSecAssert2(info != NULL, NULL);
for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
if(info[ii].intValue == intValue) {
return(&info[ii]);
}
}
return(NULL);
}
/**
* xmlSecQName2IntegerGetInteger:
* @info: the qname<->integer mapping information.
* @qnameHref: the qname href value.
* @qnameLocalPart: the qname local part value.
* @intValue: the pointer to result integer value.
*
* Maps qname qname to an integer and returns it in @intValue.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2IntegerGetInteger(xmlSecQName2IntegerInfoConstPtr info,
const xmlChar* qnameHref, const xmlChar* qnameLocalPart,
int* intValue) {
unsigned int ii;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(qnameLocalPart != NULL, -1);
xmlSecAssert2(intValue != NULL, -1);
for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) &&
xmlStrEqual(info[ii].qnameHref, qnameHref)) {
(*intValue) = info[ii].intValue;
return(0);
}
}
return(-1);
}
/**
* xmlSecQName2IntegerGetIntegerFromInteger:
* @info: the qname<->integer mapping information.
* @node: the pointer to node.
* @qname: the qname string.
* @intValue: the pointer to result integer value.
*
* Converts @qname into integer in context of @node.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info,
xmlNodePtr node, const xmlChar* qname,
int* intValue) {
const xmlChar* qnameLocalPart = NULL;
xmlChar* qnamePrefix = NULL;
const xmlChar* qnameHref;
xmlNsPtr ns;
int ret;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(qname != NULL, -1);
xmlSecAssert2(intValue != NULL, -1);
qnameLocalPart = xmlStrchr(qname, ':');
if(qnameLocalPart != NULL) {
qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
if(qnamePrefix == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlStrndup",
XMLSEC_ERRORS_R_MALLOC_FAILED,
"node=%s,value=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(qname));
return(-1);
}
qnameLocalPart++;
} else {
qnamePrefix = NULL;
qnameLocalPart = qname;
}
/* search namespace href */
ns = xmlSearchNs(node->doc, node, qnamePrefix);
if((ns == NULL) && (qnamePrefix != NULL)) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSearchNs",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s,qnamePrefix=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(qnamePrefix));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
return(-1);
}
qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
/* and finally search for integer */
ret = xmlSecQName2IntegerGetInteger(info, qnameHref, qnameLocalPart, intValue);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2IntegerGetInteger",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,qnameLocalPart=%s,qnameHref=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(qnameLocalPart),
xmlSecErrorsSafeString(qnameHref));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
return(-1);
}
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
return(0);
}
/**
* xmlSecQName2IntegerGetStringFromInteger:
* @info: the qname<->integer mapping information.
* @node: the pointer to node.
* @intValue: the integer value.
*
* Creates qname string for @intValue in context of given @node. Caller
* is responsible for freeing returned string with @xmlFree.
*
* Returns pointer to newly allocated string on success or NULL if an error occurs,
*/
EXPORT_C
xmlChar*
xmlSecQName2IntegerGetStringFromInteger(xmlSecQName2IntegerInfoConstPtr info,
xmlNodePtr node, int intValue) {
xmlSecQName2IntegerInfoConstPtr qnameInfo;
xmlSecAssert2(info != NULL, NULL);
xmlSecAssert2(node != NULL, NULL);
qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
if(qnameInfo == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2IntegerGetInfo",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,intValue=%d",
xmlSecErrorsSafeString(node->name),
intValue);
return(NULL);
}
return (xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart));
}
/**
* xmlSecQName2IntegerNodeRead:
* @info: the qname<->integer mapping information.
* @node: the pointer to node.
* @intValue: the pointer to result integer value.
*
* Reads the content of @node and converts it to an integer using mapping
* from @info.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2IntegerNodeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, int* intValue) {
xmlChar* content = NULL;
int ret;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(intValue != NULL, -1);
content = xmlNodeGetContent(node);
if(content == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNodeGetContent",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s",
xmlSecErrorsSafeString(node->name));
return(-1);
}
ret = xmlSecQName2IntegerGetIntegerFromString(info, node, content, intValue);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2IntegerGetIntegerFromString",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,value=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(content));
xmlFree(content);
return(-1);
}
xmlFree(content);
return(0);
}
/**
* xmlSecQName2IntegerNodeWrite:
* @info: the qname<->integer mapping information.
* @node: the parent node.
* @nodeName: the child node name.
* @nodeNs: the child node namespace.
* @intValue: the integer value.
*
* Creates new child node in @node and sets its value to @intValue.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2IntegerNodeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
const xmlChar* nodeName, const xmlChar* nodeNs, int intValue) {
xmlNodePtr cur;
xmlChar* qname = NULL;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(nodeName != NULL, -1);
/* find and build qname */
qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue);
if(qname == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2IntegerGetStringFromInteger",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,intValue=%d",
xmlSecErrorsSafeString(node->name),
intValue);
return(-1);
}
cur = xmlSecAddChild(node, nodeName, nodeNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecAddChild",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,intValue=%d",
xmlSecErrorsSafeString(nodeName),
intValue);
xmlFree(qname);
return(-1);
}
xmlNodeSetContent(cur, qname);
xmlFree(qname);
return(0);
}
/**
* xmlSecQName2IntegerAttributeRead:
* @info: the qname<->integer mapping information.
* @node: the element node.
* @attrName: the attribute name.
* @intValue: the pointer to result integer value.
*
* Gets the value of @attrName atrtibute from @node and converts it to integer
* according to @info.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2IntegerAttributeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
const xmlChar* attrName, int* intValue) {
xmlChar* attrValue;
int ret;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(attrName != NULL, -1);
xmlSecAssert2(intValue != NULL, -1);
attrValue = xmlGetProp(node, attrName);
if(attrValue == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlGetProp",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s,attrValue=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(attrName));
return(-1);
}
ret = xmlSecQName2IntegerGetIntegerFromString(info, node, attrValue, intValue);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2IntegerGetIntegerFromString",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,attrName=%s,attrValue=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(attrName),
xmlSecErrorsSafeString(attrValue));
xmlFree(attrValue);
return(-1);
}
xmlFree(attrValue);
return(0);
}
/**
* xmlSecQName2IntegerAttributeWrite:
* @info: the qname<->integer mapping information.
* @node: the parent node.
* @attrName: the name of attribute.
* @intValue: the integer value.
*
* Converts @intValue to a qname and sets it to the value of
* attribute @attrName in @node.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2IntegerAttributeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
const xmlChar* attrName, int intValue) {
xmlChar* qname;
xmlAttrPtr attr;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(attrName != NULL, -1);
/* find and build qname */
qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue);
if(qname == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2IntegerGetStringFromInteger",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,attrName=%s,intValue=%d",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(attrName),
intValue);
return(-1);
}
attr = xmlSetProp(node, attrName, qname);
if(attr == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecAddChildNode",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,attrName=%s,intValue=%d",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(attrName),
intValue);
xmlFree(qname);
return(-1);
}
xmlFree(qname);
return(0);
}
/**
* xmlSecQName2IntegerDebugDump:
* @info: the qname<->integer mapping information.
* @intValue: the integer value.
* @output: the pointer to output FILE.
*
* Prints @intValue into @output.
*/
EXPORT_C
void
xmlSecQName2IntegerDebugDump(xmlSecQName2IntegerInfoConstPtr info, int intValue,
const xmlChar* name, FILE* output) {
xmlSecQName2IntegerInfoConstPtr qnameInfo;
xmlSecAssert(info != NULL);
xmlSecAssert(name != NULL);
xmlSecAssert(output != NULL);
qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
if(qnameInfo != NULL) {
fprintf(output, "== %s: %d (name=\"%s\", href=\"%s\")\n", name, intValue,
(qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL,
(qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL);
}
}
/**
* xmlSecQName2IntegerDebugXmlDump:
* @info: the qname<->integer mapping information.
* @intValue: the integer value.
* @output: the pointer to output FILE.
*
* Prints @intValue into @output in XML format.
*/
EXPORT_C
void
xmlSecQName2IntegerDebugXmlDump(xmlSecQName2IntegerInfoConstPtr info, int intValue,
const xmlChar* name, FILE* output) {
xmlSecQName2IntegerInfoConstPtr qnameInfo;
xmlSecAssert(info != NULL);
xmlSecAssert(name != NULL);
xmlSecAssert(output != NULL);
qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
if(qnameInfo != NULL) {
fprintf(output, "<%s value=\"%d\" href=\"%s\">%s<%s>\n", name, intValue,
(qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL,
(qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL,
name);
}
}
/*************************************************************************
*
* QName <-> Bits mask mapping
*
************************************************************************/
/**
* xmlSecQName2BitMaskGetInfo:
* @info: the qname<->bit mask mapping information.
* @mask: the bit mask.
*
* Converts @mask to qname.
*
* Returns pointer to the qname info for @mask or NULL if mask is unknown.
*/
EXPORT_C
xmlSecQName2BitMaskInfoConstPtr
xmlSecQName2BitMaskGetInfo(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask) {
unsigned int ii;
xmlSecAssert2(info != NULL, NULL);
for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
xmlSecAssert2(info[ii].mask != 0, NULL);
if(info[ii].mask == mask) {
return(&info[ii]);
}
}
return(NULL);
}
/**
* xmlSecQName2BitMaskGetBitMask:
* @info: the qname<->bit mask mapping information.
* @qnameHref: the qname Href value.
* @qnameLocalPart: the qname LocalPart value.
* @mask: the pointer to result mask.
*
* Converts @qnameLocalPart to @mask.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2BitMaskGetBitMask(xmlSecQName2BitMaskInfoConstPtr info,
const xmlChar* qnameHref, const xmlChar* qnameLocalPart,
xmlSecBitMask* mask) {
unsigned int ii;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(qnameLocalPart != NULL, -1);
xmlSecAssert2(mask != NULL, -1);
for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
xmlSecAssert2(info[ii].mask != 0, -1);
if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) &&
xmlStrEqual(info[ii].qnameHref, qnameHref)) {
(*mask) = info[ii].mask;
return(0);
}
}
return(-1);
}
/**
* xmlSecQName2BitMaskGetBitMaskFromBitMask:
* @info: the qname<->integer mapping information.
* @node: the pointer to node.
* @qname: the qname string.
* @mask: the pointer to result msk value.
*
* Converts @qname into integer in context of @node.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info,
xmlNodePtr node, const xmlChar* qname,
xmlSecBitMask* mask) {
const xmlChar* qnameLocalPart = NULL;
xmlChar* qnamePrefix = NULL;
const xmlChar* qnameHref;
xmlNsPtr ns;
int ret;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(qname != NULL, -1);
xmlSecAssert2(mask != NULL, -1);
qnameLocalPart = xmlStrchr(qname, ':');
if(qnameLocalPart != NULL) {
qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
if(qnamePrefix == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlStrndup",
XMLSEC_ERRORS_R_MALLOC_FAILED,
"node=%s,value=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(qname));
return(-1);
}
qnameLocalPart++;
} else {
qnamePrefix = NULL;
qnameLocalPart = qname;
}
/* search namespace href */
ns = xmlSearchNs(node->doc, node, qnamePrefix);
if((ns == NULL) && (qnamePrefix != NULL)) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSearchNs",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s,qnamePrefix=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(qnamePrefix));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
return(-1);
}
qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
/* and finally search for integer */
ret = xmlSecQName2BitMaskGetBitMask(info, qnameHref, qnameLocalPart, mask);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2BitMaskGetBitMask",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,qnameLocalPart=%s,qnameHref=%s",
xmlSecErrorsSafeString(node->name),
xmlSecErrorsSafeString(qnameLocalPart),
xmlSecErrorsSafeString(qnameHref));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
return(-1);
}
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
return(0);
}
/**
* xmlSecQName2BitMaskGetStringFromBitMask:
* @info: the qname<->integer mapping information.
* @node: the pointer to node.
* @mask: the mask.
*
* Creates qname string for @mask in context of given @node. Caller
* is responsible for freeing returned string with @xmlFree.
*
* Returns pointer to newly allocated string on success or NULL if an error occurs,
*/
EXPORT_C
xmlChar*
xmlSecQName2BitMaskGetStringFromBitMask(xmlSecQName2BitMaskInfoConstPtr info,
xmlNodePtr node, xmlSecBitMask mask) {
xmlSecQName2BitMaskInfoConstPtr qnameInfo;
xmlSecAssert2(info != NULL, NULL);
xmlSecAssert2(node != NULL, NULL);
qnameInfo = xmlSecQName2BitMaskGetInfo(info, mask);
if(qnameInfo == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2BitMaskGetInfo",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s,mask=%d",
xmlSecErrorsSafeString(node->name),
mask);
return(NULL);
}
return(xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart));
}
/**
* xmlSecQName2BitMaskNodesRead:
* @info: the qname<->bit mask mapping information.
* @node: the start.
* @nodeName: the mask nodes name.
* @nodeNs: the mask nodes namespace.
* @stopOnUnknown: if this flag is set then function exits if unknown
* value was found.
* @mask: the pointer to result mask.
*
* Reads <@nodeNs:@nodeName> elements and puts the result bit mask
* into @mask. When function exits, @node points to the first element node
* after all the <@nodeNs:@nodeName> elements.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2BitMaskNodesRead(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr* node,
const xmlChar* nodeName, const xmlChar* nodeNs,
int stopOnUnknown, xmlSecBitMask* mask) {
xmlNodePtr cur;
xmlChar* content;
xmlSecBitMask tmp;
int ret;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(mask != NULL, -1);
(*mask) = 0;
cur = (*node);
while((cur != NULL) && (xmlSecCheckNodeName(cur, nodeName, nodeNs))) {
content = xmlNodeGetContent(cur);
if(content == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlNodeGetContent",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s",
xmlSecErrorsSafeString(cur->name));
return(-1);
}
ret = xmlSecQName2BitMaskGetBitMaskFromString(info, cur, content, &tmp);
if(ret < 0) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2BitMaskGetBitMaskFromString",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"value=%s",
xmlSecErrorsSafeString(content));
xmlFree(content);
return(-1);
}
if((stopOnUnknown != 0) && (tmp == 0)) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecQName2BitMaskGetBitMaskFromString",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"value=%s",
xmlSecErrorsSafeString(content));
xmlFree(content);
return(-1);
}
xmlFree(content);
(*mask) |= tmp;
cur = xmlSecGetNextElementNode(cur->next);
}
(*node) = cur;
return(0);
}
/**
* xmlSecQName2BitMaskNodesWrite:
* @info: the qname<->bit mask mapping information.
* @node: the parent element for mask nodes.
* @nodeName: the mask nodes name.
* @nodeNs: the mask nodes namespace.
* @mask: the bit mask.
*
* Writes <@nodeNs:@nodeName> elemnts with values from @mask to @node.
*
* Returns 0 on success or a negative value if an error occurs,
*/
EXPORT_C
int
xmlSecQName2BitMaskNodesWrite(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr node,
const xmlChar* nodeName, const xmlChar* nodeNs,
xmlSecBitMask mask) {
unsigned int ii;
xmlSecAssert2(info != NULL, -1);
xmlSecAssert2(node != NULL, -1);
xmlSecAssert2(nodeName != NULL, -1);
for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
xmlSecAssert2(info[ii].mask != 0, -1);
if((mask & info[ii].mask) != 0) {
xmlNodePtr cur;
xmlChar* qname;
qname = xmlSecGetQName(node, info[ii].qnameHref, info[ii].qnameLocalPart);
if(qname == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecGetQName",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s",
xmlSecErrorsSafeString(nodeName));
return(-1);
}
cur = xmlSecAddChild(node, nodeName, nodeNs);
if(cur == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
"xmlSecAddChild",
XMLSEC_ERRORS_R_XML_FAILED,
"node=%s",
xmlSecErrorsSafeString(nodeName));
xmlFree(qname);
return(-1);
}
xmlNodeSetContent(cur, qname);
xmlFree(qname);
}
}
return(0);
}
/**
* xmlSecQName2BitMaskDebugDump:
* @info: the qname<->bit mask mapping information.
* @mask: the bit mask.
* @output: the pointer to output FILE.
*
* Prints debug information about @mask to @output.
*/
EXPORT_C
void
xmlSecQName2BitMaskDebugDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask,
const xmlChar* name, FILE* output) {
unsigned int ii;
xmlSecAssert(info != NULL);
xmlSecAssert(name != NULL);
xmlSecAssert(output != NULL);
if(mask == 0) {
return;
}
fprintf(output, "== %s (0x%08x): ", name, mask);
for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
xmlSecAssert(info[ii].mask != 0);
if((mask & info[ii].mask) != 0) {
fprintf(output, "name=\"%s\" (href=\"%s\"),", info[ii].qnameLocalPart, info[ii].qnameHref);
}
}
fprintf(output, "\n");
}
/**
* xmlSecQName2BitMaskDebugXmlDump:
* @info: the qname<->bit mask mapping information.
* @mask: the bit mask.
* @output: the pointer to output FILE.
*
* Prints debug information about @mask to @output in XML format.
*/
EXPORT_C
void
xmlSecQName2BitMaskDebugXmlDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask,
const xmlChar* name, FILE* output) {
unsigned int ii;
xmlSecAssert(info != NULL);
xmlSecAssert(name != NULL);
xmlSecAssert(output != NULL);
if(mask == 0) {
return;
}
fprintf(output, "<%sList>\n", name);
for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
xmlSecAssert(info[ii].mask != 0);
if((mask & info[ii].mask) != 0) {
fprintf(output, "<%s href=\"%s\">%s</%s>\n", name,
info[ii].qnameHref, info[ii].qnameLocalPart, name);
}
}
fprintf(output, "</%sList>\n", name);
}