summaryrefslogtreecommitdiff
path: root/src/xmltree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmltree.c')
-rw-r--r--src/xmltree.c951
1 files changed, 495 insertions, 456 deletions
diff --git a/src/xmltree.c b/src/xmltree.c
index 3ef7f977..df99931d 100644
--- a/src/xmltree.c
+++ b/src/xmltree.c
@@ -1,20 +1,24 @@
-/**
+/*
* 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-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
*/
+/**
+ * SECTION:xmltree
+ * @Short_description: XML tree functions.
+ * @Stability: Stable
+ *
+ */
+
#include "globals.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <time.h>
-#include <errno.h>
#include <libxml/tree.h>
#include <libxml/valid.h>
@@ -28,6 +32,61 @@
#include <xmlsec/base64.h>
#include <xmlsec/errors.h>
+static const xmlChar* g_xmlsec_xmltree_default_linefeed = xmlSecStringCR;
+
+/**
+ * xmlSecGetDefaultLineFeed:
+ *
+ * Gets the current default linefeed.
+ *
+ * Returns: the current default linefeed.
+ */
+const xmlChar*
+xmlSecGetDefaultLineFeed(void)
+{
+ return g_xmlsec_xmltree_default_linefeed;
+}
+
+/**
+ * xmlSecSetDefaultLineFeed:
+ * @linefeed: default linefeed.
+ *
+ * Sets the current default linefeed. The caller must ensure that the linefeed
+ * string exists for the lifetime of the program or until the new linefeed is set.
+ */
+void
+xmlSecSetDefaultLineFeed(const xmlChar *linefeed)
+{
+ g_xmlsec_xmltree_default_linefeed = linefeed;
+}
+
+/**
+ * xmlSecFindSibling:
+ * @cur: the pointer to XML node.
+ * @name: the name.
+ * @ns: the namespace href (may be NULL).
+ *
+ * Searches @cur and the next siblings of the @cur 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.
+ */
+xmlNodePtr
+xmlSecFindSibling(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr tmp;
+ xmlSecAssert2(name != NULL, NULL);
+
+ for(tmp = cur; tmp != NULL; tmp = tmp->next) {
+ if(tmp->type == XML_ELEMENT_NODE) {
+ if(xmlSecCheckNodeName(tmp, name, ns)) {
+ return(tmp);
+ }
+ }
+ }
+ return(NULL);
+}
+
/**
* xmlSecFindChild:
* @parent: the pointer to XML node.
@@ -42,21 +101,10 @@
*/
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);
+ return(xmlSecFindSibling(parent->children, name, ns));
}
/**
@@ -185,13 +233,9 @@ xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
if(parent->children == NULL) {
/* TODO: add indents */
- text = xmlNewText(xmlSecStringCR);
+ text = xmlNewText(xmlSecGetDefaultLineFeed());
if(text == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewText",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewText", NULL);
return(NULL);
}
xmlAddChild(parent, text);
@@ -199,11 +243,7 @@ xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
cur = xmlNewChild(parent, NULL, name, NULL);
if(cur == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewChild",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewChild", NULL);
return(NULL);
}
@@ -215,18 +255,18 @@ xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) {
nsPtr = xmlNewNs(cur, ns, NULL);
+ if(nsPtr == NULL) {
+ xmlSecXmlError("xmlNewNs", NULL);
+ return(NULL);
+ }
}
xmlSetNs(cur, nsPtr);
}
/* TODO: add indents */
- text = xmlNewText(xmlSecStringCR);
+ text = xmlNewText(xmlSecGetDefaultLineFeed());
if(text == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewText",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewText", NULL);
return(NULL);
}
xmlAddChild(parent, text);
@@ -252,13 +292,9 @@ xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) {
if(parent->children == NULL) {
/* TODO: add indents */
- text = xmlNewText(xmlSecStringCR);
+ text = xmlNewText(xmlSecGetDefaultLineFeed());
if(text == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewText",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewText", NULL);
return(NULL);
}
xmlAddChild(parent, text);
@@ -267,13 +303,9 @@ xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) {
xmlAddChild(parent, child);
/* TODO: add indents */
- text = xmlNewText(xmlSecStringCR);
+ text = xmlNewText(xmlSecGetDefaultLineFeed());
if(text == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewText",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewText", NULL);
return(NULL);
}
xmlAddChild(parent, text);
@@ -282,6 +314,52 @@ xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) {
}
/**
+ * xmlSecEnsureEmptyChild:
+ * @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. If not found then element node with given name / namespace
+ * is added.
+ *
+ * Returns: the pointer to the found or created node; or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecEnsureEmptyChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr cur = NULL;
+ xmlNodePtr tmp;
+
+ xmlSecAssert2(parent != NULL, NULL);
+ xmlSecAssert2(name != NULL, NULL);
+
+ /* try to find an empty node first */
+ tmp = xmlSecFindNode(parent, name, ns);
+ while(tmp != NULL) {
+ cur = tmp;
+ if(xmlSecIsEmptyNode(cur) == 1) {
+ return(cur);
+ }
+ tmp = xmlSecFindSibling(cur->next, name, ns);
+ }
+
+ /* if not found then either add next or add at the end */
+ if(cur == NULL) {
+ cur = xmlSecAddChild(parent, name, ns);
+ } else if((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE)) {
+ cur = xmlSecAddNextSibling(cur->next, name, ns);
+ } else {
+ cur = xmlSecAddNextSibling(cur, name, ns);
+ }
+ if(cur == NULL) {
+ xmlSecInternalError2("xmlSecAddChild or xmlSecAddNextSibling", NULL,
+ "node=%s", xmlSecErrorsSafeString(name));
+ return(NULL);
+ }
+ return(cur);
+}
+
+/**
* xmlSecAddNextSibling
* @node: the pointer to an XML node.
* @name: the new node name.
@@ -301,11 +379,7 @@ xmlSecAddNextSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
cur = xmlNewNode(NULL, name);
if(cur == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewNode",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewNode", NULL);
return(NULL);
}
xmlAddNextSibling(node, cur);
@@ -323,13 +397,9 @@ xmlSecAddNextSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
}
/* TODO: add indents */
- text = xmlNewText(xmlSecStringCR);
+ text = xmlNewText(xmlSecGetDefaultLineFeed());
if(text == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewText",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewText", NULL);
return(NULL);
}
xmlAddNextSibling(node, text);
@@ -357,11 +427,7 @@ xmlSecAddPrevSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
cur = xmlNewNode(NULL, name);
if(cur == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewNode",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewNode", NULL);
return(NULL);
}
xmlAddPrevSibling(node, cur);
@@ -379,13 +445,9 @@ xmlSecAddPrevSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
}
/* TODO: add indents */
- text = xmlNewText(xmlSecStringCR);
+ text = xmlNewText(xmlSecGetDefaultLineFeed());
if(text == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNewText",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlNewText", NULL);
return(NULL);
}
xmlAddPrevSibling(node, text);
@@ -453,11 +515,7 @@ xmlSecReplaceNodeAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr* repl
oldNode = xmlReplaceNode(node, newNode);
if(oldNode == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlReplaceNode",
- XMLSEC_ERRORS_R_XML_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXmlError("xmlReplaceNode", NULL);
return(-1);
}
@@ -565,17 +623,15 @@ int
xmlSecReplaceNodeBufferAndReturn(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size, xmlNodePtr *replaced) {
xmlNodePtr results = NULL;
xmlNodePtr next = NULL;
+ int ret;
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");
+ ret = xmlParseInNodeContext(node->parent, (const char*)buffer, size, XML_PARSE_NODICT, &results);
+ if(ret != XML_ERR_OK) {
+ xmlSecXmlError("xmlParseInNodeContext", NULL);
return(-1);
}
@@ -615,24 +671,17 @@ xmlSecNodeEncodeAndSetContent(xmlNodePtr node, const xmlChar * buffer) {
xmlSecAssert2(node->doc != NULL, -1);
if(buffer != NULL) {
- xmlChar * tmp;
-
+ xmlChar * tmp;
tmp = xmlEncodeSpecialChars(node->doc, buffer);
if (tmp == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlEncodeSpecialChars",
- XMLSEC_ERRORS_R_XML_FAILED,
- "Failed to encode special characters");
+ xmlSecXmlError("xmlEncodeSpecialChars", NULL);
return(-1);
}
-
xmlNodeSetContent(node, tmp);
xmlFree(tmp);
} else {
xmlNodeSetContent(node, NULL);
}
-
return(0);
}
@@ -667,12 +716,7 @@ xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr cur, const xmlChar** ids) {
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));
+ xmlSecInvalidStringDataError("id", name, "unique id (id already defined)", NULL);
}
xmlFree(name);
}
@@ -694,172 +738,9 @@ xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr cur, const xmlChar** ids) {
}
/**
- * 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.
- */
-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.
- */
-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 */
- unsigned int seed = time(NULL);
- for(i = 0; i < binLen; i++) {
- (xmlSecBufferGetData(&buffer)) [i] = (xmlSecByte) (256.0 * rand_r(&seed) / (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, "%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).
+ * @rootNodeNs: the root node namespace (optional).
*
* Creates a new XML tree with one root node @rootNodeName.
*
@@ -876,22 +757,15 @@ xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) {
/* 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);
+ xmlSecXmlError("xmlNewDoc", NULL);
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");
+ xmlSecXmlError2("xmlNewDocNode", NULL,
+ "node=%s", rootNodeName);
xmlFreeDoc(doc);
return(NULL);
}
@@ -900,12 +774,8 @@ xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) {
/* 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));
+ xmlSecXmlError2("xmlNewNs", NULL,
+ "ns=%s", xmlSecErrorsSafeString(rootNodeNs));
xmlFreeDoc(doc);
return(NULL);
}
@@ -918,7 +788,7 @@ xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) {
* xmlSecIsEmptyNode:
* @node: the node to check
*
- * Checks whethere the @node is empty (i.e. has only whitespaces children).
+ * Checks whether 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.
*/
@@ -947,7 +817,7 @@ xmlSecIsEmptyNode(xmlNodePtr node) {
* xmlSecIsEmptyString:
* @str: the string to check
*
- * Checks whethere the @str is empty (i.e. has only whitespaces children).
+ * Checks whether 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.
*/
@@ -980,12 +850,8 @@ xmlSecPrintXmlString(FILE * fd, const xmlChar * str) {
xmlChar * encoded_str = NULL;
encoded_str = xmlEncodeSpecialChars(NULL, str);
if(encoded_str == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlEncodeSpecialChars",
- XMLSEC_ERRORS_R_XML_FAILED,
- "string=%s",
- xmlSecErrorsSafeString(str));
+ xmlSecXmlError2("xmlEncodeSpecialChars", NULL,
+ "string=%s", xmlSecErrorsSafeString(str));
return(-1);
}
@@ -996,12 +862,7 @@ xmlSecPrintXmlString(FILE * fd, const xmlChar * str) {
}
if(res < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "fprintf",
- XMLSEC_ERRORS_R_IO_FAILED,
- "res=%d,errno=%d",
- res, errno);
+ xmlSecIOError("fprintf", NULL, NULL);
return(-1);
}
return(res);
@@ -1023,6 +884,7 @@ xmlChar*
xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) {
xmlChar* qname;
xmlNsPtr ns;
+ int ret;
xmlSecAssert2(node != NULL, NULL);
xmlSecAssert2(local != NULL, NULL);
@@ -1031,13 +893,8 @@ xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) {
* 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));
+ xmlSecXmlError2("xmlSearchNsByHref", NULL,
+ "node=%s", xmlSecErrorsSafeString(node->name));
return(NULL);
}
@@ -1045,26 +902,22 @@ xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) {
xmlSecSize len;
len = xmlStrlen(local) + xmlStrlen(ns->prefix) + 4;
- qname = xmlMalloc(len);
+ qname = (xmlChar *)xmlMalloc(len);
if(qname == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlMalloc",
- XMLSEC_ERRORS_R_MALLOC_FAILED,
- "node=%s",
- xmlSecErrorsSafeString(node->name));
+ xmlSecMallocError(len, NULL);
+ return(NULL);
+ }
+
+ ret = xmlStrPrintf(qname, len, "%s:%s", ns->prefix, local);
+ if(ret < 0) {
+ xmlSecXmlError("xmlStrPrintf", NULL);
+ xmlFree(qname);
return(NULL);
}
- xmlSecStrPrintf(qname, len, "%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));
+ xmlSecStrdupError(local, NULL);
return(NULL);
}
}
@@ -1164,15 +1017,9 @@ xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info,
qnameLocalPart = xmlStrchr(qname, ':');
if(qnameLocalPart != NULL) {
- qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
+ qnamePrefix = xmlStrndup(qname, (int)(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));
+ xmlSecStrdupError(qname, NULL);
return(-1);
}
qnameLocalPart++;
@@ -1184,13 +1031,8 @@ xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info,
/* 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));
+ xmlSecXmlError2("xmlSearchNs", NULL,
+ "node=%s", xmlSecErrorsSafeString(node->name));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
@@ -1201,14 +1043,11 @@ xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info,
/* 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));
+ xmlSecInternalError4("xmlSecQName2IntegerGetInteger", NULL,
+ "node=%s,qnameLocalPart=%s,qnameHref=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnameLocalPart),
+ xmlSecErrorsSafeString(qnameHref));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
@@ -1243,13 +1082,10 @@ xmlSecQName2IntegerGetStringFromInteger(xmlSecQName2IntegerInfoConstPtr info,
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);
+ xmlSecInternalError3("xmlSecQName2IntegerGetInfo", NULL,
+ "node=%s,intValue=%d",
+ xmlSecErrorsSafeString(node->name),
+ intValue);
return(NULL);
}
@@ -1278,25 +1114,18 @@ xmlSecQName2IntegerNodeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr nod
content = xmlNodeGetContent(node);
if(content == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlNodeGetContent",
- XMLSEC_ERRORS_R_XML_FAILED,
- "node=%s",
- xmlSecErrorsSafeString(node->name));
+ xmlSecXmlError2("xmlNodeGetContent", NULL,
+ "node=%s", xmlSecErrorsSafeString(node->name));
return(-1);
}
/* todo: trim content? */
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));
+ xmlSecInternalError3("xmlSecQName2IntegerGetIntegerFromString", NULL,
+ "node=%s,value=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(content));
xmlFree(content);
return(-1);
}
@@ -1330,25 +1159,19 @@ xmlSecQName2IntegerNodeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr no
/* 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);
+ xmlSecInternalError3("xmlSecQName2IntegerGetStringFromInteger", NULL,
+ "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);
+ xmlSecInternalError3("xmlSecAddChild", NULL,
+ "node=%s,intValue=%d",
+ xmlSecErrorsSafeString(nodeName),
+ intValue);
xmlFree(qname);
return(-1);
}
@@ -1383,27 +1206,19 @@ xmlSecQName2IntegerAttributeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePt
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));
+ xmlSecXmlError2("xmlGetProp", NULL,
+ "node=%s", xmlSecErrorsSafeString(node->name));
return(-1);
}
/* todo: trim value? */
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));
+ xmlSecInternalError4("xmlSecQName2IntegerGetIntegerFromString", NULL,
+ "node=%s,attrName=%s,attrValue=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(attrName),
+ xmlSecErrorsSafeString(attrValue));
xmlFree(attrValue);
return(-1);
}
@@ -1437,27 +1252,21 @@ xmlSecQName2IntegerAttributeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodeP
/* 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);
+ xmlSecInternalError4("xmlSecQName2IntegerGetStringFromInteger", NULL,
+ "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);
+ xmlSecInternalError4("xmlSetProp", NULL,
+ "node=%s,attrName=%s,intValue=%d",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(attrName),
+ intValue);
xmlFree(qname);
return(-1);
}
@@ -1612,15 +1421,9 @@ xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info,
qnameLocalPart = xmlStrchr(qname, ':');
if(qnameLocalPart != NULL) {
- qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
+ qnamePrefix = xmlStrndup(qname, (int)(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));
+ xmlSecStrdupError(qname, NULL);
return(-1);
}
qnameLocalPart++;
@@ -1632,13 +1435,8 @@ xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info,
/* 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));
+ xmlSecXmlError2("xmlSearchNs", NULL,
+ "node=%s", xmlSecErrorsSafeString(node->name));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
@@ -1649,14 +1447,11 @@ xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info,
/* 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));
+ xmlSecInternalError4("xmlSecQName2BitMaskGetBitMask", NULL,
+ "node=%s,qnameLocalPart=%s,qnameHref=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnameLocalPart),
+ xmlSecErrorsSafeString(qnameHref));
if(qnamePrefix != NULL) {
xmlFree(qnamePrefix);
}
@@ -1691,13 +1486,10 @@ xmlSecQName2BitMaskGetStringFromBitMask(xmlSecQName2BitMaskInfoConstPtr info,
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);
+ xmlSecInternalError3("xmlSecQName2BitMaskGetInfo", NULL,
+ "node=%s,mask=%d",
+ xmlSecErrorsSafeString(node->name),
+ mask);
return(NULL);
}
@@ -1738,23 +1530,15 @@ xmlSecQName2BitMaskNodesRead(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr* n
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));
+ xmlSecXmlError2("xmlNodeGetContent", NULL,
+ "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));
+ xmlSecInternalError2("xmlSecQName2BitMaskGetBitMaskFromString", NULL,
+ "value=%s", xmlSecErrorsSafeString(content));
xmlFree(content);
return(-1);
}
@@ -1762,12 +1546,8 @@ xmlSecQName2BitMaskNodesRead(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr* n
if((stopOnUnknown != 0) && (tmp == 0)) {
/* todo: better error */
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecQName2BitMaskGetBitMaskFromString",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "value=%s",
- xmlSecErrorsSafeString(content));
+ xmlSecInternalError2("xmlSecQName2BitMaskGetBitMaskFromString", NULL,
+ "value=%s", xmlSecErrorsSafeString(content));
return(-1);
}
@@ -1810,23 +1590,15 @@ xmlSecQName2BitMaskNodesWrite(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr n
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));
+ xmlSecXmlError2("xmlSecGetQName", NULL,
+ "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));
+ xmlSecXmlError2("xmlSecAddChild", NULL,
+ "node=%s", xmlSecErrorsSafeString(nodeName));
xmlFree(qname);
return(-1);
}
@@ -1905,6 +1677,273 @@ xmlSecQName2BitMaskDebugXmlDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitM
fprintf(output, "</%sList>\n", name);
}
+/*************************************************************************
+ *
+ * Windows string conversions
+ *
+ ************************************************************************/
+#ifdef WIN32
+
+/**
+ * xmlSecWin32ConvertUtf8ToUnicode:
+ * @str: the string to convert.
+ *
+ * Converts input string from UTF8 to Unicode.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+LPWSTR
+xmlSecWin32ConvertUtf8ToUnicode(const xmlChar* str) {
+ LPWSTR res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* call MultiByteToWideChar first to get the buffer size */
+ ret = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, NULL, 0);
+ if(ret <= 0) {
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len);
+ if(res == NULL) {
+ xmlSecMallocError(sizeof(WCHAR) * len, NULL);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)str, -1, res, len);
+ if(ret <= 0) {
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/**
+ * xmlSecWin32ConvertUnicodeToUtf8:
+ * @str: the string to convert.
+ *
+ * Converts input string from Unicode to UTF8.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecWin32ConvertUnicodeToUtf8(LPCWSTR str) {
+ xmlChar * res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* call WideCharToMultiByte first to get the buffer size */
+ ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
+ if(ret <= 0) {
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len);
+ if(res == NULL) {
+ xmlSecMallocError(sizeof(xmlChar) * len, NULL);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, (LPSTR)res, len, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/**
+ * xmlSecWin32ConvertLocaleToUnicode:
+ * @str: the string to convert.
+ *
+ * Converts input string from current system locale to Unicode.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+LPWSTR
+xmlSecWin32ConvertLocaleToUnicode(const char* str) {
+ LPWSTR res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* call MultiByteToWideChar first to get the buffer size */
+ ret = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ if(ret <= 0) {
+ return(NULL);
+ }
+ len = ret;
+
+ /* allocate buffer */
+ res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len);
+ if(res == NULL) {
+ xmlSecMallocError(sizeof(WCHAR) * len, NULL);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = MultiByteToWideChar(CP_ACP, 0, str, -1, res, len);
+ if(ret <= 0) {
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/**
+ * xmlSecWin32ConvertLocaleToUtf8:
+ * @str: the string to convert.
+ *
+ * Converts input string from locale to UTF8.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecWin32ConvertLocaleToUtf8(const char * str) {
+ LPWSTR strW = NULL;
+ xmlChar * res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ strW = xmlSecWin32ConvertLocaleToUnicode(str);
+ if(strW == NULL) {
+ return(NULL);
+ }
+
+ /* call WideCharToMultiByte first to get the buffer size */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len);
+ if(res == NULL) {
+ xmlSecMallocError(sizeof(xmlChar) * len, NULL);
+ xmlFree(strW);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, (LPSTR)res, len, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(strW);
+ return(res);
+}
+
+/**
+ * xmlSecWin32ConvertUtf8ToLocale:
+ * @str: the string to convert.
+ *
+ * Converts input string from UTF8 to locale.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+char *
+xmlSecWin32ConvertUtf8ToLocale(const xmlChar* str) {
+ LPWSTR strW = NULL;
+ char * res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ strW = xmlSecWin32ConvertUtf8ToUnicode(str);
+ if(strW == NULL) {
+ return(NULL);
+ }
+
+ /* call WideCharToMultiByte first to get the buffer size */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (char*)xmlMalloc(sizeof(char) * len);
+ if(res == NULL) {
+ xmlSecMallocError(sizeof(char) * len, NULL);
+ xmlFree(strW);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, res, len, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(strW);
+ return(res);
+}
+
+/**
+ * xmlSecWin32ConvertTstrToUtf8:
+ * @str: the string to convert.
+ *
+ * Converts input string from TSTR (locale or Unicode) to UTF8.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecWin32ConvertTstrToUtf8(LPCTSTR str) {
+#ifdef UNICODE
+ return xmlSecWin32ConvertUnicodeToUtf8(str);
+#else /* UNICODE */
+ return xmlSecWin32ConvertLocaleToUtf8(str);
+#endif /* UNICODE */
+}
+
+/**
+ * xmlSecWin32ConvertUtf8ToTstr:
+ * @str: the string to convert.
+ *
+ * Converts input string from UTF8 to TSTR (locale or Unicode).
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+LPTSTR
+xmlSecWin32ConvertUtf8ToTstr(const xmlChar* str) {
+#ifdef UNICODE
+ return xmlSecWin32ConvertUtf8ToUnicode(str);
+#else /* UNICODE */
+ return xmlSecWin32ConvertUtf8ToLocale(str);
+#endif /* UNICODE */
+}
+
+#endif /* WIN32 */