UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
ixml.cpp
Go to the documentation of this file.
1/**************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (C) 2022 GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
6 * Redistribution only with this Copyright remark. Last modified: 2026-03-31
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * - Neither name of Intel Corporation nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 **************************************************************************/
33// Last compare with ./Pupnp source file, based on 2026-03-16, ver 1.14.30
34
39#include <ixml/ixmldebug.hpp>
40// #include "ixmlmembuf.hpp"
41#include <ixml/ixmlparser.hpp>
42
43// #include <stdlib.h> /* for free() */
44#include <cstring>
45
46// #include "posix_overwrites.hpp" // IWYU pragma: keep
47
52static void copy_with_escape(
54 ixml_membuf* buf,
56 const char* p) {
57 size_t i;
58 size_t plen;
59
60 if (!p) {
61 return;
62 }
63 plen = strlen(p);
64 for (i = (size_t)0; i < plen; ++i) {
65 switch (p[i]) {
66 case '<':
67 ixml_membuf_append_str(buf, "&lt;");
68 break;
69 case '>':
70 ixml_membuf_append_str(buf, "&gt;");
71 break;
72 case '&':
73 ixml_membuf_append_str(buf, "&amp;");
74 break;
75 case '\'':
76 ixml_membuf_append_str(buf, "&apos;");
77 break;
78 case '\"':
79 ixml_membuf_append_str(buf, "&quot;");
80 break;
81 default:
82 ixml_membuf_append(buf, &p[i]);
83 break;
84 }
85 }
86}
87
94 IXML_Node* nodeptr,
96 ixml_membuf* buf) {
97 const char* nodeName = NULL;
98 const char* nodeValue = NULL;
99 IXML_Node *child = NULL, *sibling = NULL;
100
101 if (nodeptr) {
102 nodeName = (const char*)ixmlNode_getNodeName(nodeptr);
103 nodeValue = ixmlNode_getNodeValue(nodeptr);
104
105 switch (ixmlNode_getNodeType(nodeptr)) {
106 case eTEXT_NODE:
107 copy_with_escape(buf, nodeValue);
108 break;
109
110 case eCDATA_SECTION_NODE:
111 ixml_membuf_append_str(buf, "<![CDATA[");
112 ixml_membuf_append_str(buf, nodeValue);
113 ixml_membuf_append_str(buf, "]]>");
114 break;
115
116 case ePROCESSING_INSTRUCTION_NODE:
117 ixml_membuf_append_str(buf, "<?");
118 ixml_membuf_append_str(buf, nodeName);
119 ixml_membuf_append_str(buf, " ");
120 copy_with_escape(buf, nodeValue);
121 ixml_membuf_append_str(buf, "?>\n");
122 break;
123
124 case eDOCUMENT_NODE:
126 break;
127
128 case eATTRIBUTE_NODE:
129 ixml_membuf_append_str(buf, nodeName);
130 ixml_membuf_append_str(buf, "=\"");
131 copy_with_escape(buf, nodeValue);
132 ixml_membuf_append_str(buf, "\"");
133 if (nodeptr->nextSibling) {
134 ixml_membuf_append_str(buf, " ");
135 ixmlPrintDomTreeRecursive(nodeptr->nextSibling, buf);
136 }
137 break;
138
139 case eELEMENT_NODE:
140 ixml_membuf_append_str(buf, "<");
141 ixml_membuf_append_str(buf, nodeName);
142 if (nodeptr->firstAttr) {
143 ixml_membuf_append_str(buf, " ");
144 ixmlPrintDomTreeRecursive(nodeptr->firstAttr, buf);
145 }
146 child = ixmlNode_getFirstChild(nodeptr);
147 if (child && ixmlNode_getNodeType(child) == eELEMENT_NODE) {
148 ixml_membuf_append_str(buf, ">\r\n");
149 } else {
150 ixml_membuf_append_str(buf, ">");
151 }
152 /* output the children */
154
155 /* Done with children. Output the end tag. */
156 ixml_membuf_append_str(buf, "</");
157 ixml_membuf_append_str(buf, nodeName);
158
159 sibling = ixmlNode_getNextSibling(nodeptr);
160 if (sibling && ixmlNode_getNodeType(sibling) == eTEXT_NODE) {
161 ixml_membuf_append_str(buf, ">");
162 } else {
163 ixml_membuf_append_str(buf, ">\r\n");
164 }
166 break;
167
168 default:
169 IxmlPrintf(__FILE__, __LINE__, "ixmlPrintDomTreeRecursive",
170 "Warning, unknown node type %d\n",
171 (int)ixmlNode_getNodeType(nodeptr));
172 break;
173 }
174 }
175}
176
185 IXML_Node* nodeptr,
187 ixml_membuf* buf) {
188 const char* nodeName = NULL;
189 const char* nodeValue = NULL;
190 IXML_Node* child = NULL;
191
192 if (!nodeptr || !buf) {
193 return;
194 }
195
196 nodeName = (const char*)ixmlNode_getNodeName(nodeptr);
197 nodeValue = ixmlNode_getNodeValue(nodeptr);
198 switch (ixmlNode_getNodeType(nodeptr)) {
199 case eTEXT_NODE:
200 case eCDATA_SECTION_NODE:
201 case ePROCESSING_INSTRUCTION_NODE:
202 case eDOCUMENT_NODE:
203 ixmlPrintDomTreeRecursive(nodeptr, buf);
204 break;
205
206 case eATTRIBUTE_NODE:
207 ixml_membuf_append_str(buf, nodeName);
208 ixml_membuf_append_str(buf, "=\"");
209 copy_with_escape(buf, nodeValue);
210 ixml_membuf_append_str(buf, "\"");
211 break;
212
213 case eELEMENT_NODE:
214 ixml_membuf_append_str(buf, "<");
215 ixml_membuf_append_str(buf, nodeName);
216 if (nodeptr->firstAttr) {
217 ixml_membuf_append_str(buf, " ");
218 ixmlPrintDomTreeRecursive(nodeptr->firstAttr, buf);
219 }
220 child = ixmlNode_getFirstChild(nodeptr);
221 if (child && ixmlNode_getNodeType(child) == eELEMENT_NODE) {
222 ixml_membuf_append_str(buf, ">\r\n");
223 } else {
224 ixml_membuf_append_str(buf, ">");
225 }
226
227 /* output the children */
229
230 /* Done with children. Output the end tag. */
231 ixml_membuf_append_str(buf, "</");
232 ixml_membuf_append_str(buf, nodeName);
233 ixml_membuf_append_str(buf, ">\r\n");
234 break;
235
236 default:
237 IxmlPrintf(__FILE__, __LINE__, "ixmlPrintDomTree",
238 "Warning, unknown node type %d\n",
239 (int)ixmlNode_getNodeType(nodeptr));
240 break;
241 }
242}
243
252 IXML_Node* nodeptr,
254 ixml_membuf* buf) {
255 const char* nodeName = NULL;
256 const char* nodeValue = NULL;
257 IXML_Node* child = NULL;
258
259 if (!nodeptr || !buf) {
260 return;
261 }
262
263 nodeName = (const char*)ixmlNode_getNodeName(nodeptr);
264 nodeValue = ixmlNode_getNodeValue(nodeptr);
265
266 switch (ixmlNode_getNodeType(nodeptr)) {
267 case eTEXT_NODE:
268 case eCDATA_SECTION_NODE:
269 case ePROCESSING_INSTRUCTION_NODE:
270 case eDOCUMENT_NODE:
271 ixmlPrintDomTreeRecursive(nodeptr, buf);
272 break;
273
274 case eATTRIBUTE_NODE:
275 ixml_membuf_append_str(buf, nodeName);
276 ixml_membuf_append_str(buf, "=\"");
277 copy_with_escape(buf, nodeValue);
278 ixml_membuf_append_str(buf, "\"");
279 break;
280
281 case eELEMENT_NODE:
282 ixml_membuf_append_str(buf, "<");
283 ixml_membuf_append_str(buf, nodeName);
284 if (nodeptr->firstAttr) {
285 ixml_membuf_append_str(buf, " ");
286 ixmlPrintDomTreeRecursive(nodeptr->firstAttr, buf);
287 }
288 child = ixmlNode_getFirstChild(nodeptr);
289 if (child && ixmlNode_getNodeType(child) == eELEMENT_NODE) {
290 ixml_membuf_append_str(buf, ">");
291 } else {
292 ixml_membuf_append_str(buf, ">");
293 }
294
295 /* output the children */
297
298 /* Done with children. Output the end tag. */
299 ixml_membuf_append_str(buf, "</");
300 ixml_membuf_append_str(buf, nodeName);
301 ixml_membuf_append_str(buf, ">");
302 break;
303
304 default:
305 IxmlPrintf(__FILE__, __LINE__, "ixmlPrintDomTreeRecursive",
306 "Warning, unknown node type %d\n",
307 (int)ixmlNode_getNodeType(nodeptr));
308 break;
309 }
310}
311
312int ixmlLoadDocumentEx(const char* xmlFile, IXML_Document** doc) {
313 if (!xmlFile || !doc) {
314 return IXML_INVALID_PARAMETER;
315 }
316
317 return Parser_LoadDocument(doc, xmlFile, 1);
318}
319
320IXML_Document* ixmlLoadDocument(const char* xmlFile) {
321 IXML_Document* doc = NULL;
322
323 ixmlLoadDocumentEx(xmlFile, &doc);
324
325 return doc;
326}
327
329 IXML_Node* rootNode = (IXML_Node*)doc;
330 ixml_membuf memBuf;
331 ixml_membuf* buf = &memBuf;
332
333 if (!rootNode) {
334 return NULL;
335 }
336
337 ixml_membuf_init(buf);
338 ixml_membuf_append_str(buf, "<?xml version=\"1.0\"?>\r\n");
339 ixmlPrintDomTree(rootNode, buf);
340
341 return buf->buf;
342}
343
345 ixml_membuf memBuf;
346 ixml_membuf* buf = &memBuf;
347
348 if (!node) {
349 return NULL;
350 }
351
352 ixml_membuf_init(buf);
353 ixmlPrintDomTree(node, buf);
354
355 return buf->buf;
356}
357
359 IXML_Node* rootNode = (IXML_Node*)doc;
360 ixml_membuf memBuf;
361 ixml_membuf* buf = &memBuf;
362
363 if (!rootNode) {
364 return NULL;
365 }
366
367 ixml_membuf_init(buf);
368 ixml_membuf_append_str(buf, "<?xml version=\"1.0\"?>\r\n");
369 ixmlDomTreetoString(rootNode, buf);
370
371 return buf->buf;
372}
373
375 ixml_membuf memBuf;
376 ixml_membuf* buf = &memBuf;
377
378 if (!node) {
379 return NULL;
380 }
381
382 ixml_membuf_init(buf);
383 ixmlDomTreetoString(node, buf);
384
385 return buf->buf;
386}
387
388void ixmlRelaxParser(char errorChar) { Parser_setErrorChar(errorChar); }
389
390#ifdef IXML_HAVE_SCRIPTSUPPORT
391void ixmlSetBeforeFree(IXML_BeforeFreeNode_t hndlr) {
392 Parser_setBeforeFree(hndlr);
393}
394#endif
395
396int ixmlParseBufferEx(const char* buffer, IXML_Document** retDoc) {
397 if (!buffer || !retDoc) {
398 return IXML_INVALID_PARAMETER;
399 }
400 if (buffer[0] == '\0') {
401 return IXML_INVALID_PARAMETER;
402 }
403
404 return Parser_LoadDocument(retDoc, buffer, 0);
405}
406
407IXML_Document* ixmlParseBuffer(const char* buffer) {
408 IXML_Document* doc = NULL;
409
410 ixmlParseBufferEx(buffer, &doc);
411
412 return doc;
413}
414
416 if (!src) {
417 return NULL;
418 }
419
420 return strdup(src);
421}
422
424 if (buf) {
425 free(buf);
426 }
427}
Data structure common to all types of nodes.
Definition ixml.hpp:132
Data structure representing the DOM Document.
Definition ixml.hpp:155
DOMString ixmlPrintNode(IXML_Node *node)
Renders a Node and all sub-elements into an XML text representation.
Definition ixml.cpp:344
PUPNP_Api unsigned short ixmlNode_getNodeType(IXML_Node *nodeptr)
Retrieves the type of a Node. Note that not all possible return values are actually implemented.
Definition node.cpp:322
DOMString ixmlNodetoString(IXML_Node *node)
Renders a Node and all sub-elements into an XML text representation. The caller is required to free t...
Definition ixml.cpp:374
int ixmlParseBufferEx(const char *buffer, IXML_Document **retDoc)
Parses an XML text buffer converting it into an IXML DOM representation.
Definition ixml.cpp:396
#define DOMString
The type of DOM strings.
Definition ixml.hpp:47
PUPNP_Api IXML_Node * ixmlNode_getNextSibling(IXML_Node *nodeptr)
Retrieves the sibling Node immediately following this Node.
Definition node.cpp:371
void ixmlRelaxParser(char errorChar)
Makes the XML parser more tolerant to malformed text.
Definition ixml.cpp:388
PUPNP_Api const DOMString ixmlNode_getNodeValue(IXML_Node *nodeptr)
Returns the value of the Node as a string.
Definition node.cpp:294
PUPNP_Api const DOMString ixmlNode_getNodeName(IXML_Node *nodeptr)
Returns the name of the Node, depending on what type of Node it is, in a read-only string.
Definition node.cpp:182
DOMString ixmlPrintDocument(IXML_Document *doc)
Renders a Node and all sub-elements into an XML document representation.
Definition ixml.cpp:328
DOMString ixmlDocumenttoString(IXML_Document *doc)
Renders a Node and all sub-elements into an XML document representation.
Definition ixml.cpp:358
int ixmlLoadDocumentEx(const char *xmlFile, IXML_Document **doc)
Parses an XML text file converting it into an IXML DOM representation.
Definition ixml.cpp:312
IXML_Document * ixmlLoadDocument(const char *xmlFile)
Parses an XML text file converting it into an IXML DOM representation.
Definition ixml.cpp:320
void ixmlFreeDOMString(DOMString buf)
Frees a DOMString.
Definition ixml.cpp:423
DOMString ixmlCloneDOMString(const DOMString src)
Clones an existing DOMString.
Definition ixml.cpp:415
PUPNP_Api IXML_Node * ixmlNode_getFirstChild(IXML_Node *nodeptr)
Retrieves the first child Node of a Node.
Definition node.cpp:338
IXML_Document * ixmlParseBuffer(const char *buffer)
Parses an XML text buffer converting it into an IXML DOM representation.
Definition ixml.cpp:407
static void ixmlPrintDomTree(IXML_Node *nodeptr, ixml_membuf *buf)
Print a DOM tree.
Definition ixml.cpp:183
static void ixmlPrintDomTreeRecursive(IXML_Node *nodeptr, ixml_membuf *buf)
Recursive function to print all the node in a tree. Internal to parser only.
Definition ixml.cpp:92
static void ixmlDomTreetoString(IXML_Node *nodeptr, ixml_membuf *buf)
Converts a DOM tree into a text string.
Definition ixml.cpp:250
static void copy_with_escape(ixml_membuf *buf, const char *p)
Appends a string to a buffer, substituting some characters by escape sequences.
Definition ixml.cpp:52
Auxiliar routines to aid debugging.
void IxmlPrintf(const char *DbgFileName, int DbgLineNo, const char *FunctionName, const char *FmtStr,...)
Prints the debug statement either on the standard output or log file along with the information from ...
Definition ixmldebug.cpp:18
void ixml_membuf_init(ixml_membuf *m)
ixml_membuf initialization routine.
int ixml_membuf_append(ixml_membuf *m, const void *buf)
Appends one byte to the designated ixml_membuffer.
int ixml_membuf_append_str(ixml_membuf *m, const char *c_str)
Appends the contents of a NULL terminated string to the designated ixml_membuf.
The ixml_membuf type.
int Parser_LoadDocument(IXML_Document **retDoc, const char *xmlFile, int file)
Parses a xml file and return the DOM tree.
void Parser_setErrorChar(char c)
Sets the error character.