Coverage Report

Created: 2026-09-01 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pupnp/ixml/src/document.c
Line
Count
Source
1
/*******************************************************************************
2
 *
3
 * Copyright (c) 2000-2003 Intel Corporation
4
 * All rights reserved.
5
 * Copyright (c) 2012 France Telecom All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions are met:
9
 *
10
 * - Redistributions of source code must retain the above copyright notice,
11
 * this list of conditions and the following disclaimer.
12
 * - Redistributions in binary form must reproduce the above copyright notice,
13
 * this list of conditions and the following disclaimer in the documentation
14
 * and/or other materials provided with the distribution.
15
 * - Neither name of Intel Corporation nor the names of its contributors
16
 * may be used to endorse or promote products derived from this software
17
 * without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
23
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 *
31
 ******************************************************************************/
32
33
/*!
34
 * \file
35
 */
36
37
#include "ixml.h"
38
#include "ixmldebug.h"
39
#include "ixmlparser.h"
40
41
#include <stdlib.h>
42
#include <string.h>
43
44
#include "posix_overwrites.h" // IWYU pragma: keep
45
46
void ixmlDocument_init(IXML_Document *doc)
47
3.59k
{
48
3.59k
  memset(doc, 0, sizeof(IXML_Document));
49
3.59k
}
50
51
void ixmlDocument_free(IXML_Document *doc)
52
3.59k
{
53
3.59k
  if (doc) {
54
3.59k
    ixmlNode_free((IXML_Node *)doc);
55
3.59k
  }
56
3.59k
}
57
58
/*!
59
 * When this function is called first time, nodeptr is the root of the subtree,
60
 * so it is not necessary to do two steps recursion.
61
 *
62
 * Internal function called by ixmlDocument_importNode
63
 */
64
static void ixmlDocument_setOwnerDocument(
65
  /*! [in] The document node. */
66
  IXML_Document *doc,
67
  /*! [in] \todo documentation. */
68
  IXML_Node *nodeptr)
69
0
{
70
0
  if (nodeptr) {
71
0
    nodeptr->ownerDocument = doc;
72
0
    ixmlDocument_setOwnerDocument(
73
0
      doc, ixmlNode_getFirstChild(nodeptr));
74
0
    ixmlDocument_setOwnerDocument(
75
0
      doc, ixmlNode_getNextSibling(nodeptr));
76
0
  }
77
0
}
78
79
int ixmlDocument_importNode(
80
  IXML_Document *doc, IXML_Node *importNode, int deep, IXML_Node **rtNode)
81
0
{
82
0
  unsigned short nodeType;
83
0
  IXML_Node *newNode;
84
85
0
  *rtNode = NULL;
86
87
0
  if (!doc || !importNode) {
88
0
    return IXML_INVALID_PARAMETER;
89
0
  }
90
91
0
  nodeType = ixmlNode_getNodeType(importNode);
92
0
  if (nodeType == eDOCUMENT_NODE) {
93
0
    return IXML_NOT_SUPPORTED_ERR;
94
0
  }
95
96
0
  newNode = ixmlNode_cloneNode(importNode, deep);
97
0
  if (!newNode) {
98
0
    return IXML_FAILED;
99
0
  }
100
101
0
  ixmlDocument_setOwnerDocument(doc, newNode);
102
0
  *rtNode = newNode;
103
104
0
  return IXML_SUCCESS;
105
0
}
106
107
int ixmlDocument_createElementEx(
108
  IXML_Document *doc, const DOMString tagName, IXML_Element **rtElement)
109
15.7k
{
110
15.7k
  int errCode = IXML_SUCCESS;
111
15.7k
  IXML_Element *newElement = NULL;
112
113
15.7k
  if (!doc || !tagName) {
114
0
    errCode = IXML_INVALID_PARAMETER;
115
0
    goto ErrorHandler;
116
0
  }
117
118
15.7k
  newElement = (IXML_Element *)malloc(sizeof(IXML_Element));
119
15.7k
  if (!newElement) {
120
0
    errCode = IXML_INSUFFICIENT_MEMORY;
121
0
    goto ErrorHandler;
122
0
  }
123
124
15.7k
  ixmlElement_init(newElement);
125
15.7k
  newElement->tagName = strdup(tagName);
126
15.7k
  if (!newElement->tagName) {
127
0
    ixmlElement_free(newElement);
128
0
    newElement = NULL;
129
0
    errCode = IXML_INSUFFICIENT_MEMORY;
130
0
    goto ErrorHandler;
131
0
  }
132
  /* set the node fields */
133
15.7k
  newElement->n.nodeType = eELEMENT_NODE;
134
15.7k
  newElement->n.nodeName = strdup(tagName);
135
15.7k
  if (!newElement->n.nodeName) {
136
0
    free(newElement->tagName);
137
0
    ixmlElement_free(newElement);
138
0
    newElement = NULL;
139
0
    errCode = IXML_INSUFFICIENT_MEMORY;
140
0
    goto ErrorHandler;
141
0
  }
142
143
15.7k
  newElement->n.ownerDocument = doc;
144
145
15.7k
ErrorHandler:
146
15.7k
  *rtElement = newElement;
147
148
15.7k
  return errCode;
149
15.7k
}
150
151
IXML_Element *ixmlDocument_createElement(
152
  IXML_Document *doc, const DOMString tagName)
153
0
{
154
0
  IXML_Element *newElement = NULL;
155
0
  int ret = IXML_SUCCESS;
156
157
0
  ret = ixmlDocument_createElementEx(doc, tagName, &newElement);
158
0
  if (ret != IXML_SUCCESS) {
159
0
    IxmlPrintf(__FILE__,
160
0
      __LINE__,
161
0
      "ixmlDocument_createElement",
162
0
      "Error %d\n",
163
0
      ret);
164
0
    return NULL;
165
0
  }
166
0
  return newElement;
167
0
}
168
169
int ixmlDocument_createDocumentEx(IXML_Document **rtDoc)
170
3.59k
{
171
3.59k
  IXML_Document *doc;
172
3.59k
  int errCode = IXML_SUCCESS;
173
174
3.59k
  doc = NULL;
175
3.59k
  doc = (IXML_Document *)malloc(sizeof(IXML_Document));
176
3.59k
  if (!doc) {
177
0
    errCode = IXML_INSUFFICIENT_MEMORY;
178
0
    goto ErrorHandler;
179
0
  }
180
181
3.59k
  ixmlDocument_init(doc);
182
183
3.59k
  doc->n.nodeName = strdup((const char *)DOCUMENTNODENAME);
184
3.59k
  if (!doc->n.nodeName) {
185
0
    ixmlDocument_free(doc);
186
0
    doc = NULL;
187
0
    errCode = IXML_INSUFFICIENT_MEMORY;
188
0
    goto ErrorHandler;
189
0
  }
190
191
3.59k
  doc->n.nodeType = eDOCUMENT_NODE;
192
3.59k
  doc->n.ownerDocument = doc;
193
194
3.59k
ErrorHandler:
195
  /* doc is NULL on failure */
196
3.59k
  *rtDoc = doc;
197
3.59k
  return errCode;
198
3.59k
}
199
200
IXML_Document *ixmlDocument_createDocument(void)
201
0
{
202
0
  IXML_Document *doc = NULL;
203
204
0
  ixmlDocument_createDocumentEx(&doc);
205
206
0
  return doc;
207
0
}
208
209
int ixmlDocument_createTextNodeEx(
210
  IXML_Document *doc, const DOMString data, IXML_Node **textNode)
211
3.51k
{
212
3.51k
  IXML_Node *returnNode;
213
3.51k
  int rc = IXML_SUCCESS;
214
215
3.51k
  returnNode = NULL;
216
3.51k
  if (!doc || !data) {
217
0
    rc = IXML_INVALID_PARAMETER;
218
0
    goto ErrorHandler;
219
0
  }
220
221
3.51k
  returnNode = (IXML_Node *)malloc(sizeof(IXML_Node));
222
3.51k
  if (!returnNode) {
223
0
    rc = IXML_INSUFFICIENT_MEMORY;
224
0
    goto ErrorHandler;
225
0
  }
226
  /* initialize the node */
227
3.51k
  ixmlNode_init(returnNode);
228
229
3.51k
  returnNode->nodeName = strdup((const char *)TEXTNODENAME);
230
3.51k
  if (!returnNode->nodeName) {
231
0
    ixmlNode_free(returnNode);
232
0
    returnNode = NULL;
233
0
    rc = IXML_INSUFFICIENT_MEMORY;
234
0
    goto ErrorHandler;
235
0
  }
236
  /* add in node value */
237
3.51k
  if (data) {
238
3.51k
    returnNode->nodeValue = strdup(data);
239
3.51k
    if (!returnNode->nodeValue) {
240
0
      ixmlNode_free(returnNode);
241
0
      returnNode = NULL;
242
0
      rc = IXML_INSUFFICIENT_MEMORY;
243
0
      goto ErrorHandler;
244
0
    }
245
3.51k
  }
246
247
3.51k
  returnNode->nodeType = eTEXT_NODE;
248
3.51k
  returnNode->ownerDocument = doc;
249
250
3.51k
ErrorHandler:
251
3.51k
  *textNode = returnNode;
252
3.51k
  return rc;
253
3.51k
}
254
255
IXML_Node *ixmlDocument_createTextNode(IXML_Document *doc, const DOMString data)
256
0
{
257
0
  IXML_Node *returnNode = NULL;
258
259
0
  ixmlDocument_createTextNodeEx(doc, data, &returnNode);
260
261
0
  return returnNode;
262
0
}
263
264
int ixmlDocument_createAttributeEx(
265
  IXML_Document *doc, const DOMString name, IXML_Attr **rtAttr)
266
5.90k
{
267
5.90k
  int errCode = IXML_SUCCESS;
268
5.90k
  IXML_Attr *attrNode = NULL;
269
270
5.90k
  if (!doc || !name) {
271
0
    errCode = IXML_INVALID_PARAMETER;
272
0
    goto ErrorHandler;
273
0
  }
274
5.90k
  attrNode = (IXML_Attr *)malloc(sizeof(IXML_Attr));
275
5.90k
  if (!attrNode) {
276
0
    errCode = IXML_INSUFFICIENT_MEMORY;
277
0
    goto ErrorHandler;
278
0
  }
279
5.90k
  ixmlAttr_init(attrNode);
280
5.90k
  attrNode->n.nodeType = eATTRIBUTE_NODE;
281
  /* set the node fields */
282
5.90k
  attrNode->n.nodeName = strdup(name);
283
5.90k
  if (!attrNode->n.nodeName) {
284
0
    ixmlAttr_free(attrNode);
285
0
    attrNode = NULL;
286
0
    errCode = IXML_INSUFFICIENT_MEMORY;
287
0
    goto ErrorHandler;
288
0
  }
289
5.90k
  attrNode->n.ownerDocument = doc;
290
291
5.90k
ErrorHandler:
292
5.90k
  *rtAttr = attrNode;
293
5.90k
  return errCode;
294
5.90k
}
295
296
IXML_Attr *ixmlDocument_createAttribute(
297
  IXML_Document *doc, const DOMString name)
298
0
{
299
0
  IXML_Attr *attrNode = NULL;
300
301
0
  if (ixmlDocument_createAttributeEx(doc, name, &attrNode) !=
302
0
    IXML_SUCCESS)
303
0
    return NULL;
304
305
0
  return attrNode;
306
0
}
307
308
int ixmlDocument_createAttributeNSEx(IXML_Document *doc,
309
  const DOMString namespaceURI,
310
  const DOMString qualifiedName,
311
  IXML_Attr **rtAttr)
312
0
{
313
0
  int errCode = IXML_SUCCESS;
314
0
  IXML_Attr *attrNode = NULL;
315
316
0
  if (!doc || !namespaceURI || !qualifiedName) {
317
0
    errCode = IXML_INVALID_PARAMETER;
318
0
    goto ErrorHandler;
319
0
  }
320
321
0
  errCode = ixmlDocument_createAttributeEx(doc, qualifiedName, &attrNode);
322
0
  if (errCode != IXML_SUCCESS) {
323
0
    goto ErrorHandler;
324
0
  }
325
  /* set the namespaceURI field */
326
0
  attrNode->n.namespaceURI = strdup(namespaceURI);
327
0
  if (!attrNode->n.namespaceURI) {
328
0
    ixmlAttr_free(attrNode);
329
0
    attrNode = NULL;
330
0
    errCode = IXML_INSUFFICIENT_MEMORY;
331
0
    goto ErrorHandler;
332
0
  }
333
  /* set the localName and prefix */
334
0
  errCode = ixmlNode_setNodeName((IXML_Node *)attrNode, qualifiedName);
335
0
  if (errCode != IXML_SUCCESS) {
336
0
    ixmlAttr_free(attrNode);
337
0
    attrNode = NULL;
338
0
    goto ErrorHandler;
339
0
  }
340
341
0
ErrorHandler:
342
0
  *rtAttr = attrNode;
343
0
  return errCode;
344
0
}
345
346
IXML_Attr *ixmlDocument_createAttributeNS(IXML_Document *doc,
347
  const DOMString namespaceURI,
348
  const DOMString qualifiedName)
349
0
{
350
0
  IXML_Attr *attrNode = NULL;
351
352
0
  ixmlDocument_createAttributeNSEx(
353
0
    doc, namespaceURI, qualifiedName, &attrNode);
354
355
0
  return attrNode;
356
0
}
357
358
int ixmlDocument_createCDATASectionEx(
359
  IXML_Document *doc, const DOMString data, IXML_CDATASection **rtCD)
360
235
{
361
235
  int errCode = IXML_SUCCESS;
362
235
  IXML_CDATASection *cDSectionNode = NULL;
363
364
235
  if (!doc || !data) {
365
0
    errCode = IXML_INVALID_PARAMETER;
366
0
    goto ErrorHandler;
367
0
  }
368
369
235
  cDSectionNode = (IXML_CDATASection *)malloc(sizeof(IXML_CDATASection));
370
235
  if (!cDSectionNode) {
371
0
    errCode = IXML_INSUFFICIENT_MEMORY;
372
0
    goto ErrorHandler;
373
0
  }
374
375
235
  ixmlCDATASection_init(cDSectionNode);
376
235
  cDSectionNode->n.nodeType = eCDATA_SECTION_NODE;
377
235
  cDSectionNode->n.nodeName = strdup((const char *)CDATANODENAME);
378
235
  if (!cDSectionNode->n.nodeName) {
379
0
    ixmlCDATASection_free(cDSectionNode);
380
0
    cDSectionNode = NULL;
381
0
    errCode = IXML_INSUFFICIENT_MEMORY;
382
0
    goto ErrorHandler;
383
0
  }
384
385
235
  cDSectionNode->n.nodeValue = strdup(data);
386
235
  if (!cDSectionNode->n.nodeValue) {
387
0
    ixmlCDATASection_free(cDSectionNode);
388
0
    cDSectionNode = NULL;
389
0
    errCode = IXML_INSUFFICIENT_MEMORY;
390
0
    goto ErrorHandler;
391
0
  }
392
393
235
  cDSectionNode->n.ownerDocument = doc;
394
395
235
ErrorHandler:
396
235
  *rtCD = cDSectionNode;
397
235
  return errCode;
398
235
}
399
400
IXML_CDATASection *ixmlDocument_createCDATASection(
401
  IXML_Document *doc, const DOMString data)
402
0
{
403
0
  IXML_CDATASection *cDSectionNode = NULL;
404
405
0
  ixmlDocument_createCDATASectionEx(doc, data, &cDSectionNode);
406
407
0
  return cDSectionNode;
408
0
}
409
410
int ixmlDocument_createElementNSEx(IXML_Document *doc,
411
  const DOMString namespaceURI,
412
  const DOMString qualifiedName,
413
  IXML_Element **rtElement)
414
0
{
415
0
  IXML_Element *newElement = NULL;
416
0
  int ret = IXML_SUCCESS;
417
0
  int line = 0;
418
419
0
  if (!doc || !namespaceURI || !qualifiedName) {
420
0
    line = __LINE__;
421
0
    ret = IXML_INVALID_PARAMETER;
422
0
    goto ErrorHandler;
423
0
  }
424
425
0
  ret = ixmlDocument_createElementEx(doc, qualifiedName, &newElement);
426
0
  if (ret != IXML_SUCCESS) {
427
0
    line = __LINE__;
428
0
    goto ErrorHandler;
429
0
  }
430
  /* set the namespaceURI field */
431
0
  newElement->n.namespaceURI = strdup(namespaceURI);
432
0
  if (!newElement->n.namespaceURI) {
433
0
    line = __LINE__;
434
0
    ixmlElement_free(newElement);
435
0
    newElement = NULL;
436
0
    ret = IXML_INSUFFICIENT_MEMORY;
437
0
    goto ErrorHandler;
438
0
  }
439
  /* set the localName and prefix */
440
0
  ret = ixmlNode_setNodeName((IXML_Node *)newElement, qualifiedName);
441
0
  if (ret != IXML_SUCCESS) {
442
0
    line = __LINE__;
443
0
    ixmlElement_free(newElement);
444
0
    newElement = NULL;
445
0
    ret = IXML_INSUFFICIENT_MEMORY;
446
0
    goto ErrorHandler;
447
0
  }
448
449
0
  newElement->n.nodeValue = NULL;
450
451
0
ErrorHandler:
452
0
  *rtElement = newElement;
453
0
  if (ret != IXML_SUCCESS) {
454
0
    IxmlPrintf(__FILE__,
455
0
      line,
456
0
      "ixmlDocument_createElementNSEx",
457
0
      "Error %d\n",
458
0
      ret);
459
0
  }
460
461
0
  return ret;
462
0
}
463
464
IXML_Element *ixmlDocument_createElementNS(IXML_Document *doc,
465
  const DOMString namespaceURI,
466
  const DOMString qualifiedName)
467
0
{
468
0
  IXML_Element *newElement = NULL;
469
470
0
  ixmlDocument_createElementNSEx(
471
0
    doc, namespaceURI, qualifiedName, &newElement);
472
473
0
  return newElement;
474
0
}
475
476
IXML_NodeList *ixmlDocument_getElementsByTagName(
477
  IXML_Document *doc, const DOMString tagName)
478
0
{
479
0
  IXML_NodeList *returnNodeList = NULL;
480
481
0
  if (!doc || !tagName) {
482
0
    return NULL;
483
0
  }
484
485
0
  ixmlNode_getElementsByTagName(
486
0
    (IXML_Node *)doc, tagName, &returnNodeList);
487
488
0
  return returnNodeList;
489
0
}
490
491
IXML_NodeList *ixmlDocument_getElementsByTagNameNS(IXML_Document *doc,
492
  const DOMString namespaceURI,
493
  const DOMString localName)
494
0
{
495
0
  IXML_NodeList *returnNodeList = NULL;
496
497
0
  if (!doc || !namespaceURI || !localName) {
498
0
    return NULL;
499
0
  }
500
501
0
  ixmlNode_getElementsByTagNameNS(
502
0
    (IXML_Node *)doc, namespaceURI, localName, &returnNodeList);
503
504
0
  return returnNodeList;
505
0
}
506
507
IXML_Element *ixmlDocument_getElementById(
508
  IXML_Document *doc, const DOMString tagName)
509
0
{
510
0
  IXML_Element *rtElement = NULL;
511
0
  IXML_Node *nodeptr = (IXML_Node *)doc;
512
0
  const char *name;
513
514
0
  if (!nodeptr || !tagName) {
515
0
    return rtElement;
516
0
  }
517
518
0
  if (ixmlNode_getNodeType(nodeptr) == eELEMENT_NODE) {
519
0
    name = ixmlNode_getNodeName(nodeptr);
520
0
    if (!name) {
521
0
      return rtElement;
522
0
    }
523
524
0
    if (strcmp(tagName, name) == 0) {
525
0
      rtElement = (IXML_Element *)nodeptr;
526
0
      return rtElement;
527
0
    } else {
528
0
      rtElement = ixmlDocument_getElementById(
529
0
        (IXML_Document *)ixmlNode_getFirstChild(
530
0
          nodeptr),
531
0
        tagName);
532
0
      if (!rtElement) {
533
0
        rtElement = ixmlDocument_getElementById(
534
0
          (IXML_Document *)
535
0
            ixmlNode_getNextSibling(
536
0
              nodeptr),
537
0
          tagName);
538
0
      }
539
0
    }
540
0
  } else {
541
0
    rtElement = ixmlDocument_getElementById(
542
0
      (IXML_Document *)ixmlNode_getFirstChild(nodeptr),
543
0
      tagName);
544
0
    if (!rtElement) {
545
0
      rtElement = ixmlDocument_getElementById(
546
0
        (IXML_Document *)ixmlNode_getNextSibling(
547
0
          nodeptr),
548
0
        tagName);
549
0
    }
550
0
  }
551
552
0
  return rtElement;
553
0
}