Coverage Report

Created: 2025-08-26 07:06

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