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