pupnp (libupnp) snapshot from SourceForge: git clone git://pupnp.git.sourceforge...
[igd2-for-linux:pandonghui1211s-igd2-for-linux.git] / pupnp_branch-1.6.x / ixml / src / ixml.c
1 /**************************************************************************
2  *
3  * Copyright (c) 2000-2003 Intel Corporation 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions are met: 
8  *
9  * - Redistributions of source code must retain the above copyright notice, 
10  * this list of conditions and the following disclaimer. 
11  * - Redistributions in binary form must reproduce the above copyright notice, 
12  * this list of conditions and the following disclaimer in the documentation 
13  * and/or other materials provided with the distribution. 
14  * - Neither name of Intel Corporation nor the names of its contributors 
15  * may be used to endorse or promote products derived from this software 
16  * without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  **************************************************************************/
31
32
33 /*!
34  * \file
35  */
36
37
38 #include "ixmldebug.h"
39 #include "ixmlmembuf.h"
40 #include "ixmlparser.h"
41
42
43 #include <stdlib.h> /* for free() */
44 #include <string.h>
45
46
47 /*!
48  * \brief Appends a string to a buffer, substituting some characters by escape
49  * sequences.
50  */
51 static void copy_with_escape(
52         /*! [in,out] The input/output buffer. */
53         ixml_membuf *buf,
54         /*! [in] The string to copy from. */
55         const char *p)
56 {
57         int i;
58         int plen;
59
60         if (p == NULL) {
61                 return;
62         }
63
64         plen = strlen( p );
65
66         for (i = 0; i < plen; i++) {
67                 switch (p[i]) {
68                 case '<':
69                         ixml_membuf_append_str(buf, "&lt;");
70                         break;
71
72                 case '>':
73                         ixml_membuf_append_str(buf, "&gt;");
74                         break;
75
76                 case '&':
77                         ixml_membuf_append_str(buf, "&amp;");
78                         break;
79
80                 case '\'':
81                         ixml_membuf_append_str(buf, "&apos;");
82                         break;
83
84                 case '\"':
85                         ixml_membuf_append_str(buf, "&quot;");
86                         break;
87
88                 default:
89                         ixml_membuf_append(buf, &p[i]);
90                         break;
91                 }
92         }
93 }
94
95
96 /*!
97  * \brief Recursive function to print all the node in a tree.
98  * Internal to parser only.
99  */
100 static void ixmlPrintDomTreeRecursive(
101         /*! [in] \todo documentation. */
102         IXML_Node *nodeptr,
103         /*! [in] \todo documentation. */
104         ixml_membuf *buf)
105 {
106         const char *nodeName = NULL;
107         const char *nodeValue = NULL;
108         IXML_Node *child = NULL,
109         *sibling = NULL;
110
111         if (nodeptr != NULL) {
112                 nodeName = (const char *)ixmlNode_getNodeName(nodeptr);
113                 nodeValue = ixmlNode_getNodeValue(nodeptr);
114                 
115                 switch (ixmlNode_getNodeType(nodeptr)) {
116                 case eTEXT_NODE:
117                         copy_with_escape(buf, nodeValue);
118                         break;
119
120                 case eCDATA_SECTION_NODE:
121                         ixml_membuf_append_str(buf, "<![CDATA[");
122                         ixml_membuf_append_str(buf, nodeValue);
123                         ixml_membuf_append_str(buf, "]]>");
124                         break;
125
126                 case ePROCESSING_INSTRUCTION_NODE:
127                         ixml_membuf_append_str(buf, "<?");
128                         ixml_membuf_append_str(buf, nodeName);
129                         ixml_membuf_append_str(buf, " ");
130                         copy_with_escape(buf, nodeValue);
131                         ixml_membuf_append_str(buf, "?>\n");
132                         break;
133
134                 case eDOCUMENT_NODE:
135                         ixmlPrintDomTreeRecursive(
136                                 ixmlNode_getFirstChild(nodeptr), buf);
137                         break;
138
139                 case eATTRIBUTE_NODE:
140                         ixml_membuf_append_str(buf, nodeName);
141                         ixml_membuf_append_str(buf, "=\"");
142                         copy_with_escape(buf, nodeValue);
143                         ixml_membuf_append_str(buf, "\"");
144                         if (nodeptr->nextSibling != NULL) {
145                                 ixml_membuf_append_str(buf, " ");
146                                 ixmlPrintDomTreeRecursive(nodeptr->nextSibling, buf);
147                         }
148                         break;
149
150                 case eELEMENT_NODE:
151                         ixml_membuf_append_str(buf, "<");
152                         ixml_membuf_append_str(buf, nodeName);
153                         if (nodeptr->firstAttr != NULL) {
154                                 ixml_membuf_append_str(buf, " ");
155                                 ixmlPrintDomTreeRecursive(nodeptr->firstAttr, buf);
156                         }
157                         child = ixmlNode_getFirstChild(nodeptr);
158                         if (child != NULL &&
159                             ixmlNode_getNodeType(child) == eELEMENT_NODE) {
160                                 ixml_membuf_append_str(buf, ">\r\n");
161                         } else {
162                                 ixml_membuf_append_str(buf, ">");
163                         }
164                         //  output the children
165                         ixmlPrintDomTreeRecursive(
166                                 ixmlNode_getFirstChild(nodeptr), buf);
167
168                         // Done with children.  Output the end tag.
169                         ixml_membuf_append_str(buf, "</");
170                         ixml_membuf_append_str(buf, nodeName);
171
172                         sibling = ixmlNode_getNextSibling(nodeptr);
173                         if (sibling != NULL &&
174                             ixmlNode_getNodeType(sibling) == eTEXT_NODE) {
175                                 ixml_membuf_append_str( buf, ">" );
176                         } else {
177                                 ixml_membuf_append_str( buf, ">\r\n" );
178                         }
179                         ixmlPrintDomTreeRecursive(
180                                 ixmlNode_getNextSibling(nodeptr), buf);
181                         break;
182
183                 default:
184                         IxmlPrintf("(%s::ixmlPrintDomTreeRecursive) line %d: "
185                                 "Warning, unknown node type %d\n",
186                                 __FILE__, __LINE__, ixmlNode_getNodeType(nodeptr));
187                         break;
188                 }
189         }
190 }
191
192
193 /*!
194  * \brief Print a DOM tree.
195  *
196  * Element, and Attribute nodes are handled differently. We don't want to print
197  * the Element and Attribute nodes' sibling.
198  */
199 static void ixmlPrintDomTree(
200         /*! [in] \todo documentation. */
201         IXML_Node *nodeptr,
202         /*! [in] \todo documentation. */
203         ixml_membuf *buf)
204 {
205         const char *nodeName = NULL;
206         const char *nodeValue = NULL;
207         IXML_Node *child = NULL;
208
209         if (nodeptr == NULL || buf == NULL) {
210                 return;
211         }
212
213         nodeName = (const char *)ixmlNode_getNodeName(nodeptr);
214         nodeValue = ixmlNode_getNodeValue(nodeptr);
215         switch (ixmlNode_getNodeType(nodeptr)) {
216         case eTEXT_NODE:
217         case eCDATA_SECTION_NODE:
218         case ePROCESSING_INSTRUCTION_NODE:
219         case eDOCUMENT_NODE:
220                 ixmlPrintDomTreeRecursive(nodeptr, buf);
221                 break;
222
223         case eATTRIBUTE_NODE:
224                 ixml_membuf_append_str(buf, nodeName);
225                 ixml_membuf_append_str(buf, "=\"");
226                 copy_with_escape(buf, nodeValue);
227                 ixml_membuf_append_str(buf, "\"");
228                 break;
229
230         case eELEMENT_NODE:
231                 ixml_membuf_append_str(buf, "<");
232                 ixml_membuf_append_str(buf, nodeName);
233                 if (nodeptr->firstAttr != NULL) {
234                         ixml_membuf_append_str(buf, " ");
235                         ixmlPrintDomTreeRecursive(nodeptr->firstAttr, buf);
236                 }
237                 child = ixmlNode_getFirstChild(nodeptr);
238                 if (child != NULL &&
239                     ixmlNode_getNodeType(child) == eELEMENT_NODE) {
240                         ixml_membuf_append_str(buf, ">\r\n");
241                 } else {
242                         ixml_membuf_append_str(buf, ">");
243                 }
244
245                 // output the children
246                 ixmlPrintDomTreeRecursive(
247                         ixmlNode_getFirstChild(nodeptr), buf);
248
249                 // Done with children. Output the end tag.
250                 ixml_membuf_append_str(buf, "</");
251                 ixml_membuf_append_str(buf, nodeName);
252                 ixml_membuf_append_str(buf, ">\r\n");
253                 break;
254
255         default:
256                 IxmlPrintf("(%s::ixmlPrintDomTree) line %d: "
257                         "Warning, unknown node type %d\n",
258                         __FILE__, __LINE__, ixmlNode_getNodeType(nodeptr));
259                 break;
260         }
261 }
262
263
264 /*!
265  * \brief Converts a DOM tree into a text string.
266  *
267  * Element, and Attribute nodes are handled differently. We don't want to print
268  * the Element and Attribute nodes' sibling.
269  */
270 static void ixmlDomTreetoString(
271         /*! [in] \todo documentation. */
272         IXML_Node *nodeptr,
273         /*! [in] \todo documentation. */
274         ixml_membuf *buf)
275 {
276         const char *nodeName = NULL;
277         const char *nodeValue = NULL;
278         IXML_Node *child = NULL;
279
280         if (nodeptr == NULL || buf == NULL) {
281                 return;
282         }
283
284         nodeName = (const char *)ixmlNode_getNodeName(nodeptr);
285         nodeValue = ixmlNode_getNodeValue(nodeptr);
286
287         switch (ixmlNode_getNodeType(nodeptr)) {
288         case eTEXT_NODE:
289         case eCDATA_SECTION_NODE:
290         case ePROCESSING_INSTRUCTION_NODE:
291         case eDOCUMENT_NODE:
292                 ixmlPrintDomTreeRecursive(nodeptr, buf);
293                 break;
294
295         case eATTRIBUTE_NODE:
296                 ixml_membuf_append_str(buf, nodeName);
297                 ixml_membuf_append_str(buf, "=\"");
298                 copy_with_escape(buf, nodeValue );
299                 ixml_membuf_append_str(buf, "\"");
300                 break;
301
302         case eELEMENT_NODE:
303                 ixml_membuf_append_str(buf, "<");
304                 ixml_membuf_append_str(buf, nodeName);
305                 if (nodeptr->firstAttr != NULL) {
306                         ixml_membuf_append_str(buf, " ");
307                         ixmlPrintDomTreeRecursive(nodeptr->firstAttr, buf);
308                 }
309                 child = ixmlNode_getFirstChild(nodeptr);
310                 if (child != NULL &&
311                     ixmlNode_getNodeType(child) == eELEMENT_NODE) {
312                         ixml_membuf_append_str(buf, ">");
313                 } else {
314                         ixml_membuf_append_str(buf, ">");
315                 }
316
317                 //  output the children
318                 ixmlPrintDomTreeRecursive(ixmlNode_getFirstChild(nodeptr), buf);
319
320                 // Done with children.  Output the end tag.
321                 ixml_membuf_append_str(buf, "</");
322                 ixml_membuf_append_str(buf, nodeName);
323                 ixml_membuf_append_str(buf, ">");
324                 break;
325
326         default:
327                 IxmlPrintf("(%s::ixmlDomTreetoString) line %d: "
328                         "Warning, unknown node type %d\n",
329                         __FILE__, __LINE__, ixmlNode_getNodeType(nodeptr));
330                 break;
331         }
332 }
333
334
335 int ixmlLoadDocumentEx(const char *xmlFile, IXML_Document **doc)
336 {
337         if (xmlFile == NULL || doc == NULL) {
338                 return IXML_INVALID_PARAMETER;
339         }
340
341         return Parser_LoadDocument(doc, xmlFile, TRUE);
342 }
343
344
345 IXML_Document *ixmlLoadDocument(const char *xmlFile)
346 {
347         IXML_Document *doc = NULL;
348
349         ixmlLoadDocumentEx(xmlFile, &doc);
350
351         return doc;
352 }
353
354
355 DOMString ixmlPrintDocument(IXML_Document *doc)
356 {
357         IXML_Node* rootNode = (IXML_Node *)doc;
358         ixml_membuf memBuf;
359         ixml_membuf *buf = &memBuf;
360
361         if(rootNode == NULL) {
362                 return NULL;
363         }
364
365         ixml_membuf_init(buf);
366         ixml_membuf_append_str(buf, "<?xml version=\"1.0\"?>\r\n");
367         ixmlPrintDomTree(rootNode, buf);
368
369         return buf->buf;
370 }
371
372
373 DOMString ixmlPrintNode(IXML_Node *node)
374 {
375         ixml_membuf memBuf;
376         ixml_membuf *buf = &memBuf;
377
378         if (node == NULL) {
379                 return NULL;
380         }
381
382         ixml_membuf_init(buf);
383         ixmlPrintDomTree(node, buf);
384
385         return buf->buf;
386 }
387
388
389 DOMString ixmlDocumenttoString(IXML_Document *doc)
390 {
391         IXML_Node* rootNode = (IXML_Node *)doc;
392         ixml_membuf memBuf;
393         ixml_membuf *buf = &memBuf;
394
395         if(rootNode == NULL) {
396                 return NULL;
397         }
398
399         ixml_membuf_init(buf);
400         ixml_membuf_append_str(buf, "<?xml version=\"1.0\"?>\r\n");
401         ixmlDomTreetoString(rootNode, buf);
402
403         return buf->buf;
404 }
405
406
407 DOMString ixmlNodetoString(IXML_Node *node)
408 {
409         ixml_membuf memBuf;
410         ixml_membuf *buf = &memBuf;
411
412         if (node == NULL) {
413                 return NULL;
414         }
415
416         ixml_membuf_init(buf);
417         ixmlDomTreetoString(node, buf);
418
419         return buf->buf;
420 }
421
422
423 void ixmlRelaxParser(char errorChar)
424 {
425         Parser_setErrorChar(errorChar);
426 }
427
428
429 int ixmlParseBufferEx(const char *buffer, IXML_Document **retDoc)
430 {
431         if (buffer == NULL || retDoc == NULL) {
432                 return IXML_INVALID_PARAMETER;
433         }
434
435         if (buffer[0] == '\0') {
436                 return IXML_INVALID_PARAMETER;
437         }
438
439         return Parser_LoadDocument(retDoc, buffer, FALSE);
440 }
441
442
443 IXML_Document *ixmlParseBuffer(const char *buffer)
444 {
445         IXML_Document *doc = NULL;
446
447         ixmlParseBufferEx(buffer, &doc);
448
449         return doc;
450 }
451
452
453 DOMString ixmlCloneDOMString(const DOMString src)
454 {
455         if (src == NULL) {
456                 return NULL;
457         }
458
459         return strdup(src);
460 }
461
462
463 void ixmlFreeDOMString(DOMString buf)
464 {
465         if (buf != NULL) {
466                 free(buf);
467         }
468 }
469