Coverage Report

Created: 2026-04-10 06:50

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 "ixmldebug.h"
38
#include "ixmlparser.h"
39
40
#include <stdlib.h>
41
#include <string.h>
42
43
#include "posix_overwrites.h" // IWYU pragma: keep
44
45
void ixmlDocument_init(IXML_Document *doc)
46
3.23k
{
47
3.23k
  memset(doc, 0, sizeof(IXML_Document));
48
3.23k
}
49
50
void ixmlDocument_free(IXML_Document *doc)
51
3.23k
{
52
3.23k
  if (doc) {
53
3.23k
    ixmlNode_free((IXML_Node *)doc);
54
3.23k
  }
55
3.23k
}
56
57
/*!
58
 * When this function is called first time, nodeptr is the root of the subtree,
59
 * so it is not necessary to do two steps recursion.
60
 *
61
 * Internal function called by ixmlDocument_importNode
62
 */
63
static void ixmlDocument_setOwnerDocument(
64
  /*! [in] The document node. */
65
  IXML_Document *doc,
66
  /*! [in] \todo documentation. */
67
  IXML_Node *nodeptr)
68
0
{
69
0
  if (nodeptr) {
70
0
    nodeptr->ownerDocument = doc;
71
0
    ixmlDocument_setOwnerDocument(
72
0
      doc, ixmlNode_getFirstChild(nodeptr));
73
0
    ixmlDocument_setOwnerDocument(
74
0
      doc, ixmlNode_getNextSibling(nodeptr));
75
0
  }
76
0
}
77
78
int ixmlDocument_importNode(
79
  IXML_Document *doc, IXML_Node *importNode, int deep, IXML_Node **rtNode)
80
0
{
81
0
  unsigned short nodeType;
82
0
  IXML_Node *newNode;
83
84
0
  *rtNode = NULL;
85
86
0
  if (!doc || !importNode) {
87
0
    return IXML_INVALID_PARAMETER;
88
0
  }
89
90
0
  nodeType = ixmlNode_getNodeType(importNode);
91
0
  if (nodeType == eDOCUMENT_NODE) {
92
0
    return IXML_NOT_SUPPORTED_ERR;
93
0
  }
94
95
0
  newNode = ixmlNode_cloneNode(importNode, deep);
96
0
  if (!newNode) {
97
0
    return IXML_FAILED;
98
0
  }
99
100
0
  ixmlDocument_setOwnerDocument(doc, newNode);
101
0
  *rtNode = newNode;
102
103
0
  return IXML_SUCCESS;
104
0
}
105
106
int ixmlDocument_createElementEx(
107
  IXML_Document *doc, const DOMString tagName, IXML_Element **rtElement)
108
21.2k
{
109
21.2k
  int errCode = IXML_SUCCESS;
110
21.2k
  IXML_Element *newElement = NULL;
111
112
21.2k
  if (!doc || !tagName) {
113
0
    errCode = IXML_INVALID_PARAMETER;
114
0
    goto ErrorHandler;
115
0
  }
116
117
21.2k
  newElement = (IXML_Element *)malloc(sizeof(IXML_Element));
118
21.2k
  if (!newElement) {
119
0
    errCode = IXML_INSUFFICIENT_MEMORY;
120
0
    goto ErrorHandler;
121
0
  }
122
123
21.2k
  ixmlElement_init(newElement);
124
21.2k
  newElement->tagName = strdup(tagName);
125
21.2k
  if (!newElement->tagName) {
126
0
    ixmlElement_free(newElement);
127
0
    newElement = NULL;
128
0
    errCode = IXML_INSUFFICIENT_MEMORY;
129
0
    goto ErrorHandler;
130
0
  }
131
  /* set the node fields */
132
21.2k
  newElement->n.nodeType = eELEMENT_NODE;
133
21.2k
  newElement->n.nodeName = strdup(tagName);
134
21.2k
  if (!newElement->n.nodeName) {
135
0
    free(newElement->tagName);
136
0
    ixmlElement_free(newElement);
137
0
    newElement = NULL;
138
0
    errCode = IXML_INSUFFICIENT_MEMORY;
139
0
    goto ErrorHandler;
140
0
  }
141
142
21.2k
  newElement->n.ownerDocument = doc;
143
144
21.2k
ErrorHandler:
145
21.2k
  *rtElement = newElement;
146
147
21.2k
  return errCode;
148
21.2k
}
149
150
IXML_Element *ixmlDocument_createElement(
151
  IXML_Document *doc, const DOMString tagName)
152
0
{
153
0
  IXML_Element *newElement = NULL;
154
0
  int ret = IXML_SUCCESS;
155
156
0
  ret = ixmlDocument_createElementEx(doc, tagName, &newElement);
157
0
  if (ret != IXML_SUCCESS) {
158
0
    IxmlPrintf(__FILE__,
159
0
      __LINE__,
160
0
      "ixmlDocument_createElement",
161
0
      "Error %d\n",
162
0
      ret);
163
0
    return NULL;
164
0
  }
165
0
  return newElement;
166
0
}
167
168
int ixmlDocument_createDocumentEx(IXML_Document **rtDoc)
169
3.23k
{
170
3.23k
  IXML_Document *doc;
171
3.23k
  int errCode = IXML_SUCCESS;
172
173
3.23k
  doc = NULL;
174
3.23k
  doc = (IXML_Document *)malloc(sizeof(IXML_Document));
175
3.23k
  if (!doc) {
176
0
    errCode = IXML_INSUFFICIENT_MEMORY;
177
0
    goto ErrorHandler;
178
0
  }
179
180
3.23k
  ixmlDocument_init(doc);
181
182
3.23k
  doc->n.nodeName = strdup((const char *)DOCUMENTNODENAME);
183
3.23k
  if (!doc->n.nodeName) {
184
0
    ixmlDocument_free(doc);
185
0
    doc = NULL;
186
0
    errCode = IXML_INSUFFICIENT_MEMORY;
187
0
    goto ErrorHandler;
188
0
  }
189
190
3.23k
  doc->n.nodeType = eDOCUMENT_NODE;
191
3.23k
  doc->n.ownerDocument = doc;
192
193
3.23k
ErrorHandler:
194
  /* doc is NULL on failure */
195
3.23k
  *rtDoc = doc;
196
3.23k
  return errCode;
197
3.23k
}
198
199
IXML_Document *ixmlDocument_createDocument(void)
200
0
{
201
0
  IXML_Document *doc = NULL;
202
203
0
  ixmlDocument_createDocumentEx(&doc);
204
205
0
  return doc;
206
0
}
207
208
int ixmlDocument_createTextNodeEx(
209
  IXML_Document *doc, const DOMString data, IXML_Node **textNode)
210
2.80k
{
211
2.80k
  IXML_Node *returnNode;
212
2.80k
  int rc = IXML_SUCCESS;
213
214
2.80k
  returnNode = NULL;
215
2.80k
  if (!doc || !data) {
216
0
    rc = IXML_INVALID_PARAMETER;
217
0
    goto ErrorHandler;
218
0
  }
219
220
2.80k
  returnNode = (IXML_Node *)malloc(sizeof(IXML_Node));
221
2.80k
  if (!returnNode) {
222
0
    rc = IXML_INSUFFICIENT_MEMORY;
223
0
    goto ErrorHandler;
224
0
  }
225
  /* initialize the node */
226
2.80k
  ixmlNode_init(returnNode);
227
228
2.80k
  returnNode->nodeName = strdup((const char *)TEXTNODENAME);
229
2.80k
  if (!returnNode->nodeName) {
230
0
    ixmlNode_free(returnNode);
231
0
    returnNode = NULL;
232
0
    rc = IXML_INSUFFICIENT_MEMORY;
233
0
    goto ErrorHandler;
234
0
  }
235
  /* add in node value */
236
2.80k
  if (data) {
237
2.80k
    returnNode->nodeValue = strdup(data);
238
2.80k
    if (!returnNode->nodeValue) {
239
0
      ixmlNode_free(returnNode);
240
0
      returnNode = NULL;
241
0
      rc = IXML_INSUFFICIENT_MEMORY;
242
0
      goto ErrorHandler;
243
0
    }
244
2.80k
  }
245
246
2.80k
  returnNode->nodeType = eTEXT_NODE;
247
2.80k
  returnNode->ownerDocument = doc;
248
249
2.80k
ErrorHandler:
250
2.80k
  *textNode = returnNode;
251
2.80k
  return rc;
252
2.80k
}
253
254
IXML_Node *ixmlDocument_createTextNode(IXML_Document *doc, const DOMString data)
255
0
{
256
0
  IXML_Node *returnNode = NULL;
257
258
0
  ixmlDocument_createTextNodeEx(doc, data, &returnNode);
259
260
0
  return returnNode;
261
0
}
262
263
int ixmlDocument_createAttributeEx(
264
  IXML_Document *doc, const DOMString name, IXML_Attr **rtAttr)
265
5.73k
{
266
5.73k
  int errCode = IXML_SUCCESS;
267
5.73k
  IXML_Attr *attrNode = NULL;
268
269
5.73k
  if (!doc || !name) {
270
0
    errCode = IXML_INVALID_PARAMETER;
271
0
    goto ErrorHandler;
272
0
  }
273
5.73k
  attrNode = (IXML_Attr *)malloc(sizeof(IXML_Attr));
274
5.73k
  if (!attrNode) {
275
0
    errCode = IXML_INSUFFICIENT_MEMORY;
276
0
    goto ErrorHandler;
277
0
  }
278
5.73k
  ixmlAttr_init(attrNode);
279
5.73k
  attrNode->n.nodeType = eATTRIBUTE_NODE;
280
  /* set the node fields */
281
5.73k
  attrNode->n.nodeName = strdup(name);
282
5.73k
  if (!attrNode->n.nodeName) {
283
0
    ixmlAttr_free(attrNode);
284
0
    attrNode = NULL;
285
0
    errCode = IXML_INSUFFICIENT_MEMORY;
286
0
    goto ErrorHandler;
287
0
  }
288
5.73k
  attrNode->n.ownerDocument = doc;
289
290
5.73k
ErrorHandler:
291
5.73k
  *rtAttr = attrNode;
292
5.73k
  return errCode;
293
5.73k
}
294
295
IXML_Attr *ixmlDocument_createAttribute(
296
  IXML_Document *doc, const DOMString name)
297
0
{
298
0
  IXML_Attr *attrNode = NULL;
299
300
0
  if (ixmlDocument_createAttributeEx(doc, name, &attrNode) !=
301
0
    IXML_SUCCESS)
302
0
    return NULL;
303
304
0
  return attrNode;
305
0
}
306
307
int ixmlDocument_createAttributeNSEx(IXML_Document *doc,
308
  const DOMString namespaceURI,
309
  const DOMString qualifiedName,
310
  IXML_Attr **rtAttr)
311
0
{
312
0
  int errCode = IXML_SUCCESS;
313
0
  IXML_Attr *attrNode = NULL;
314
315
0
  if (!doc || !namespaceURI || !qualifiedName) {
316
0
    errCode = IXML_INVALID_PARAMETER;
317
0
    goto ErrorHandler;
318
0
  }
319
320
0
  errCode = ixmlDocument_createAttributeEx(doc, qualifiedName, &attrNode);
321
0
  if (errCode != IXML_SUCCESS) {
322
0
    goto ErrorHandler;
323
0
  }
324
  /* set the namespaceURI field */
325
0
  attrNode->n.namespaceURI = strdup(namespaceURI);
326
0
  if (!attrNode->n.namespaceURI) {
327
0
    ixmlAttr_free(attrNode);
328
0
    attrNode = NULL;
329
0
    errCode = IXML_INSUFFICIENT_MEMORY;
330
0
    goto ErrorHandler;
331
0
  }
332
  /* set the localName and prefix */
333
0
  errCode = ixmlNode_setNodeName((IXML_Node *)attrNode, qualifiedName);
334
0
  if (errCode != IXML_SUCCESS) {
335
0
    ixmlAttr_free(attrNode);
336
0
    attrNode = NULL;
337
0
    goto ErrorHandler;
338
0
  }
339
340
0
ErrorHandler:
341
0
  *rtAttr = attrNode;
342
0
  return errCode;
343
0
}
344
345
IXML_Attr *ixmlDocument_createAttributeNS(IXML_Document *doc,
346
  const DOMString namespaceURI,
347
  const DOMString qualifiedName)
348
0
{
349
0
  IXML_Attr *attrNode = NULL;
350
351
0
  ixmlDocument_createAttributeNSEx(
352
0
    doc, namespaceURI, qualifiedName, &attrNode);
353
354
0
  return attrNode;
355
0
}
356
357
int ixmlDocument_createCDATASectionEx(
358
  IXML_Document *doc, const DOMString data, IXML_CDATASection **rtCD)
359
327
{
360
327
  int errCode = IXML_SUCCESS;
361
327
  IXML_CDATASection *cDSectionNode = NULL;
362
363
327
  if (!doc || !data) {
364
0
    errCode = IXML_INVALID_PARAMETER;
365
0
    goto ErrorHandler;
366
0
  }
367
368
327
  cDSectionNode = (IXML_CDATASection *)malloc(sizeof(IXML_CDATASection));
369
327
  if (!cDSectionNode) {
370
0
    errCode = IXML_INSUFFICIENT_MEMORY;
371
0
    goto ErrorHandler;
372
0
  }
373
374
327
  ixmlCDATASection_init(cDSectionNode);
375
327
  cDSectionNode->n.nodeType = eCDATA_SECTION_NODE;
376
327
  cDSectionNode->n.nodeName = strdup((const char *)CDATANODENAME);
377
327
  if (!cDSectionNode->n.nodeName) {
378
0
    ixmlCDATASection_free(cDSectionNode);
379
0
    cDSectionNode = NULL;
380
0
    errCode = IXML_INSUFFICIENT_MEMORY;
381
0
    goto ErrorHandler;
382
0
  }
383
384
327
  cDSectionNode->n.nodeValue = strdup(data);
385
327
  if (!cDSectionNode->n.nodeValue) {
386
0
    ixmlCDATASection_free(cDSectionNode);
387
0
    cDSectionNode = NULL;
388
0
    errCode = IXML_INSUFFICIENT_MEMORY;
389
0
    goto ErrorHandler;
390
0
  }
391
392
327
  cDSectionNode->n.ownerDocument = doc;
393
394
327
ErrorHandler:
395
327
  *rtCD = cDSectionNode;
396
327
  return errCode;
397
327
}
398
399
IXML_CDATASection *ixmlDocument_createCDATASection(
400
  IXML_Document *doc, const DOMString data)
401
0
{
402
0
  IXML_CDATASection *cDSectionNode = NULL;
403
404
0
  ixmlDocument_createCDATASectionEx(doc, data, &cDSectionNode);
405
406
0
  return cDSectionNode;
407
0
}
408
409
int ixmlDocument_createElementNSEx(IXML_Document *doc,
410
  const DOMString namespaceURI,
411
  const DOMString qualifiedName,
412
  IXML_Element **rtElement)
413
0
{
414
0
  IXML_Element *newElement = NULL;
415
0
  int ret = IXML_SUCCESS;
416
0
  int line = 0;
417
418
0
  if (!doc || !namespaceURI || !qualifiedName) {
419
0
    line = __LINE__;
420
0
    ret = IXML_INVALID_PARAMETER;
421
0
    goto ErrorHandler;
422
0
  }
423
424
0
  ret = ixmlDocument_createElementEx(doc, qualifiedName, &newElement);
425
0
  if (ret != IXML_SUCCESS) {
426
0
    line = __LINE__;
427
0
    goto ErrorHandler;
428
0
  }
429
  /* set the namespaceURI field */
430
0
  newElement->n.namespaceURI = strdup(namespaceURI);
431
0
  if (!newElement->n.namespaceURI) {
432
0
    line = __LINE__;
433
0
    ixmlElement_free(newElement);
434
0
    newElement = NULL;
435
0
    ret = IXML_INSUFFICIENT_MEMORY;
436
0
    goto ErrorHandler;
437
0
  }
438
  /* set the localName and prefix */
439
0
  ret = ixmlNode_setNodeName((IXML_Node *)newElement, qualifiedName);
440
0
  if (ret != IXML_SUCCESS) {
441
0
    line = __LINE__;
442
0
    ixmlElement_free(newElement);
443
0
    newElement = NULL;
444
0
    ret = IXML_INSUFFICIENT_MEMORY;
445
0
    goto ErrorHandler;
446
0
  }
447
448
0
  newElement->n.nodeValue = NULL;
449
450
0
ErrorHandler:
451
0
  *rtElement = newElement;
452
0
  if (ret != IXML_SUCCESS) {
453
0
    IxmlPrintf(__FILE__,
454
0
      line,
455
0
      "ixmlDocument_createElementNSEx",
456
0
      "Error %d\n",
457
0
      ret);
458
0
  }
459
460
0
  return ret;
461
0
}
462
463
IXML_Element *ixmlDocument_createElementNS(IXML_Document *doc,
464
  const DOMString namespaceURI,
465
  const DOMString qualifiedName)
466
0
{
467
0
  IXML_Element *newElement = NULL;
468
469
0
  ixmlDocument_createElementNSEx(
470
0
    doc, namespaceURI, qualifiedName, &newElement);
471
472
0
  return newElement;
473
0
}
474
475
IXML_NodeList *ixmlDocument_getElementsByTagName(
476
  IXML_Document *doc, const DOMString tagName)
477
0
{
478
0
  IXML_NodeList *returnNodeList = NULL;
479
480
0
  if (!doc || !tagName) {
481
0
    return NULL;
482
0
  }
483
484
0
  ixmlNode_getElementsByTagName(
485
0
    (IXML_Node *)doc, tagName, &returnNodeList);
486
487
0
  return returnNodeList;
488
0
}
489
490
IXML_NodeList *ixmlDocument_getElementsByTagNameNS(IXML_Document *doc,
491
  const DOMString namespaceURI,
492
  const DOMString localName)
493
0
{
494
0
  IXML_NodeList *returnNodeList = NULL;
495
496
0
  if (!doc || !namespaceURI || !localName) {
497
0
    return NULL;
498
0
  }
499
500
0
  ixmlNode_getElementsByTagNameNS(
501
0
    (IXML_Node *)doc, namespaceURI, localName, &returnNodeList);
502
503
0
  return returnNodeList;
504
0
}
505
506
IXML_Element *ixmlDocument_getElementById(
507
  IXML_Document *doc, const DOMString tagName)
508
0
{
509
0
  IXML_Element *rtElement = NULL;
510
0
  IXML_Node *nodeptr = (IXML_Node *)doc;
511
0
  const char *name;
512
513
0
  if (!nodeptr || !tagName) {
514
0
    return rtElement;
515
0
  }
516
517
0
  if (ixmlNode_getNodeType(nodeptr) == eELEMENT_NODE) {
518
0
    name = ixmlNode_getNodeName(nodeptr);
519
0
    if (!name) {
520
0
      return rtElement;
521
0
    }
522
523
0
    if (strcmp(tagName, name) == 0) {
524
0
      rtElement = (IXML_Element *)nodeptr;
525
0
      return rtElement;
526
0
    } else {
527
0
      rtElement = ixmlDocument_getElementById(
528
0
        (IXML_Document *)ixmlNode_getFirstChild(
529
0
          nodeptr),
530
0
        tagName);
531
0
      if (!rtElement) {
532
0
        rtElement = ixmlDocument_getElementById(
533
0
          (IXML_Document *)
534
0
            ixmlNode_getNextSibling(
535
0
              nodeptr),
536
0
          tagName);
537
0
      }
538
0
    }
539
0
  } else {
540
0
    rtElement = ixmlDocument_getElementById(
541
0
      (IXML_Document *)ixmlNode_getFirstChild(nodeptr),
542
0
      tagName);
543
0
    if (!rtElement) {
544
0
      rtElement = ixmlDocument_getElementById(
545
0
        (IXML_Document *)ixmlNode_getNextSibling(
546
0
          nodeptr),
547
0
        tagName);
548
0
    }
549
0
  }
550
551
0
  return rtElement;
552
0
}