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 '&') 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