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 /*!
35  * \file
36  */
37 
38 
39 #include "ixmlparser.h"
40 
41 
42 #include <assert.h>
43 #include <stdlib.h> /* for free(), malloc() */
44 #include <string.h>
45 
46 
ixmlNode_init(IXML_Node * nodeptr)47 void ixmlNode_init(IXML_Node *nodeptr)
48 {
49 	assert(nodeptr != NULL);
50 
51 	memset(nodeptr, 0, sizeof (IXML_Node));
52 }
53 
54 
ixmlCDATASection_init(IXML_CDATASection * nodeptr)55 void ixmlCDATASection_init(IXML_CDATASection *nodeptr)
56 {
57 	memset(nodeptr, 0, sizeof (IXML_CDATASection));
58 }
59 
60 
ixmlCDATASection_free(IXML_CDATASection * nodeptr)61 void ixmlCDATASection_free(IXML_CDATASection *nodeptr)
62 {
63 	if (nodeptr != NULL) {
64 		ixmlNode_free((IXML_Node *)nodeptr);
65 	}
66 }
67 
68 
69 /*!
70  * \brief Frees a node content.
71  */
ixmlNode_freeSingleNode(IXML_Node * nodeptr)72 static void ixmlNode_freeSingleNode(
73 	/*! [in] The node to free. */
74 	IXML_Node *nodeptr)
75 {
76 	IXML_Element *element = NULL;
77 
78 	if (nodeptr != NULL) {
79 		if (nodeptr->nodeName != NULL) {
80 			free(nodeptr->nodeName);
81 		}
82 		if (nodeptr->nodeValue != NULL) {
83 			free(nodeptr->nodeValue);
84 		}
85 		if (nodeptr->namespaceURI != NULL) {
86 			free(nodeptr->namespaceURI);
87 		}
88 		if (nodeptr->prefix != NULL) {
89 			free(nodeptr->prefix);
90 		}
91 		if (nodeptr->localName != NULL) {
92 			free(nodeptr->localName);
93 		}
94 		switch (nodeptr->nodeType ) {
95 		case eELEMENT_NODE:
96 			element = (IXML_Element *)nodeptr;
97 			free(element->tagName);
98 			break;
99 		default:
100 			break;
101 		}
102 		free(nodeptr);
103 	}
104 }
105 
106 #if 0
107 /*
108  * Old implementation of ixmlNode_free(). Due to its recursive nature, it was
109  * succeptible to attacks overflowing the stack.
110  *
111  * void ixmlNode_free(IXML_Node *nodeptr)
112  */
113 void ixmlNode_recursive_free(IXML_Node *nodeptr)
114 {
115 	if (nodeptr != NULL) {
116 #ifdef IXML_HAVE_SCRIPTSUPPORT
117 		IXML_BeforeFreeNode_t hndlr = Parser_getBeforeFree();
118 		if (hndlr != NULL) hndlr(nodeptr);
119 #endif
120 		ixmlNode_free(nodeptr->firstChild);
121 		ixmlNode_free(nodeptr->nextSibling);
122 		ixmlNode_free(nodeptr->firstAttr);
123 		ixmlNode_freeSingleNode(nodeptr);
124 	}
125 }
126 #endif
127 
128 /*
129  *  void ixmlNode_non_recursive_free(IXML_Node *nodeptr)
130  */
ixmlNode_free(IXML_Node * nodeptr)131 void ixmlNode_free(IXML_Node *nodeptr)
132 {
133         IXML_Node *curr_child;
134         IXML_Node *prev_child;
135         IXML_Node *next_child;
136         IXML_Node *curr_attr;
137         IXML_Node *next_attr;
138 
139         if (nodeptr) {
140 #ifdef IXML_HAVE_SCRIPTSUPPORT
141                 IXML_BeforeFreeNode_t hndlr = Parser_getBeforeFree();
142 #endif
143                 prev_child = nodeptr;
144                 next_child = nodeptr->firstChild;
145                 do {
146                         curr_child = next_child;
147                         do {
148                                 while (curr_child) {
149                                         prev_child = curr_child;
150                                         curr_child = curr_child->firstChild;
151                                 }
152                                 curr_child = prev_child;
153                                 while (curr_child) {
154                                         prev_child = curr_child;
155                                         curr_child = curr_child->nextSibling;
156                                 }
157                                 curr_child = prev_child;
158                                 next_child = curr_child->firstChild;
159                         } while (next_child);
160                         curr_child = prev_child;
161                         /* current is now the last sibling of the last child. */
162                         /* Delete the attribute nodes of this child */
163                         /* Attribute nodes only have siblings. */
164                         curr_attr = curr_child->firstAttr;
165                         while (curr_attr) {
166                                 next_attr = curr_attr->nextSibling;
167                                 ixmlNode_freeSingleNode(curr_attr);
168                                 curr_attr = next_attr;
169                         }
170                         curr_child->firstAttr = 0;
171                         /* Return */
172                         if (curr_child != nodeptr) {
173                                 if (curr_child->prevSibling) {
174                                         next_child = curr_child->prevSibling;
175                                         next_child->nextSibling = 0;
176                                 } else {
177                                         next_child = curr_child->parentNode;
178                                         next_child->firstChild = 0;
179                                 }
180                         }
181 #ifdef IXML_HAVE_SCRIPTSUPPORT
182                         if (hndlr) {
183                                 hndlr(curr_child);
184                         }
185 #endif
186                         ixmlNode_freeSingleNode(curr_child);
187                 } while (curr_child != nodeptr);
188         }
189 }
190 
191 
ixmlNode_getNodeName(IXML_Node * nodeptr)192 const DOMString ixmlNode_getNodeName(IXML_Node *nodeptr)
193 {
194 	if(nodeptr != NULL) {
195 		return nodeptr->nodeName;
196 	}
197 
198 	return NULL;
199 }
200 
201 
ixmlNode_getLocalName(IXML_Node * nodeptr)202 const DOMString ixmlNode_getLocalName(IXML_Node *nodeptr)
203 {
204 	if (nodeptr != NULL) {
205 		return nodeptr->localName;
206 	}
207 
208 	return NULL;
209 }
210 
211 
212 /*!
213  * \brief Sets the namespace URI of the node.
214  */
ixmlNode_setNamespaceURI(IXML_Node * nodeptr,const char * namespaceURI)215 static int ixmlNode_setNamespaceURI(
216 	/*! [in] The \b Node on which to operate. */
217 	IXML_Node *nodeptr,
218 	/*! [in] The name space string to set. */
219 	const char *namespaceURI)
220 {
221 	if (nodeptr == NULL) {
222 		return IXML_INVALID_PARAMETER;
223 	}
224 
225 	if (nodeptr->namespaceURI != NULL) {
226 		free(nodeptr->namespaceURI);
227 		nodeptr->namespaceURI = NULL;
228 	}
229 
230 	if (namespaceURI != NULL) {
231 		nodeptr->namespaceURI = strdup(namespaceURI);
232 		if (nodeptr->namespaceURI == NULL) {
233 			return IXML_INSUFFICIENT_MEMORY;
234 		}
235 	}
236 
237 	return IXML_SUCCESS;
238 }
239 
240 
241 /*
242  * \brief Set the prefix of the node.
243  */
ixmlNode_setPrefix(IXML_Node * nodeptr,const char * prefix)244 static int ixmlNode_setPrefix(
245 	/*! [in] The \b Node on which to operate. */
246 	IXML_Node *nodeptr,
247 	/*! [in] The prefix string to set. */
248 	const char *prefix)
249 {
250 	if (nodeptr == NULL) {
251 		return IXML_INVALID_PARAMETER;
252 	}
253 
254 	if (nodeptr->prefix != NULL) {
255 		free(nodeptr->prefix);
256 		nodeptr->prefix = NULL;
257 	}
258 
259 	if (prefix != NULL) {
260 		nodeptr->prefix = strdup(prefix);
261 		if(nodeptr->prefix == NULL) {
262 			return IXML_INSUFFICIENT_MEMORY;
263 		}
264 	}
265 
266 	return IXML_SUCCESS;
267 }
268 
269 
270 /*!
271  * \brief Set the localName of the node.
272  *
273  * \return IXML_SUCCESS or failure.
274  */
ixmlNode_setLocalName(IXML_Node * nodeptr,const char * localName)275 static int ixmlNode_setLocalName(
276 	/*! [in] The pointer to the node. */
277 	IXML_Node *nodeptr,
278 	/*! [in] The local name to set. */
279 	const char *localName)
280 {
281 	assert(nodeptr != NULL);
282 
283 	if (nodeptr->localName != NULL) {
284 		free(nodeptr->localName);
285 		nodeptr->localName = NULL;
286 	}
287 
288 	if (localName != NULL) {
289 		nodeptr->localName = strdup(localName);
290 		if (nodeptr->localName == NULL) {
291 			return IXML_INSUFFICIENT_MEMORY;
292 		}
293 	}
294 
295 	return IXML_SUCCESS;
296 }
297 
298 
ixmlNode_getNamespaceURI(IXML_Node * nodeptr)299 const DOMString ixmlNode_getNamespaceURI(IXML_Node *nodeptr)
300 {
301 	DOMString retNamespaceURI = NULL;
302 
303 	if (nodeptr != NULL) {
304 		retNamespaceURI = nodeptr->namespaceURI;
305 	}
306 
307 	return retNamespaceURI;
308 }
309 
310 
ixmlNode_getPrefix(IXML_Node * nodeptr)311 const DOMString ixmlNode_getPrefix(IXML_Node *nodeptr)
312 {
313 	const DOMString prefix = NULL;
314 
315 	if (nodeptr != NULL) {
316 		prefix = nodeptr->prefix;
317 	}
318 
319 	return prefix;
320 }
321 
322 
ixmlNode_getNodeValue(IXML_Node * nodeptr)323 const DOMString ixmlNode_getNodeValue(IXML_Node *nodeptr)
324 {
325 	if ( nodeptr != NULL ) {
326 		return nodeptr->nodeValue;
327 	}
328 
329 	return NULL;
330 }
331 
332 
ixmlNode_setNodeValue(IXML_Node * nodeptr,const char * newNodeValue)333 int ixmlNode_setNodeValue(IXML_Node *nodeptr, const char *newNodeValue)
334 {
335 	int rc = IXML_SUCCESS;
336 
337 	if (nodeptr == NULL) {
338 		return IXML_INVALID_PARAMETER;
339 	}
340 
341 	if (nodeptr->nodeValue != NULL) {
342 		free(nodeptr->nodeValue);
343 		nodeptr->nodeValue = NULL;
344 	}
345 
346 	if (newNodeValue != NULL) {
347 		nodeptr->nodeValue = strdup(newNodeValue);
348 		if (nodeptr->nodeValue == NULL) {
349 			return IXML_INSUFFICIENT_MEMORY;
350 		}
351 	}
352 
353 	return rc;
354 }
355 
356 
ixmlNode_getNodeType(IXML_Node * nodeptr)357 unsigned short ixmlNode_getNodeType(IXML_Node *nodeptr)
358 {
359 	if (nodeptr != NULL) {
360 		return nodeptr->nodeType;
361 	} else {
362 		return (unsigned short)eINVALID_NODE;
363 	}
364 }
365 
366 
ixmlNode_getParentNode(IXML_Node * nodeptr)367 IXML_Node *ixmlNode_getParentNode(IXML_Node *nodeptr)
368 {
369 	if (nodeptr != NULL) {
370 		return nodeptr->parentNode;
371 	} else {
372 		return NULL;
373 	}
374 }
375 
376 
ixmlNode_getFirstChild(IXML_Node * nodeptr)377 IXML_Node *ixmlNode_getFirstChild(IXML_Node *nodeptr)
378 {
379 	if (nodeptr != NULL) {
380 		return nodeptr->firstChild;
381 	} else {
382 		return NULL;
383 	}
384 }
385 
386 
ixmlNode_getLastChild(IXML_Node * nodeptr)387 IXML_Node *ixmlNode_getLastChild(IXML_Node *nodeptr)
388 {
389 	IXML_Node *prev;
390 	IXML_Node *next;
391 
392 	if (nodeptr != NULL) {
393 		prev = nodeptr;
394 		next = nodeptr->firstChild;
395 		while (next != NULL) {
396 			prev = next;
397 			next = next->nextSibling;
398 		}
399 		return prev;
400 	} else {
401 		return NULL;
402 	}
403 }
404 
405 
ixmlNode_getPreviousSibling(IXML_Node * nodeptr)406 IXML_Node *ixmlNode_getPreviousSibling(IXML_Node *nodeptr)
407 {
408 	if (nodeptr != NULL) {
409 		return nodeptr->prevSibling;
410 	} else {
411 		return NULL;
412 	}
413 }
414 
415 
ixmlNode_getNextSibling(IXML_Node * nodeptr)416 IXML_Node *ixmlNode_getNextSibling(IXML_Node *nodeptr)
417 {
418 	if (nodeptr != NULL) {
419 		return nodeptr->nextSibling;
420 	} else {
421 		return NULL;
422 	}
423 }
424 
425 
ixmlNode_getOwnerDocument(IXML_Node * nodeptr)426 IXML_Document *ixmlNode_getOwnerDocument(IXML_Node *nodeptr)
427 {
428 	if (nodeptr != NULL) {
429 		return (IXML_Document *)nodeptr->ownerDocument;
430 	} else {
431 		return NULL;
432 	}
433 }
434 
435 /*!
436  * \brief Check if ancestorNode is ancestor of toFind.
437  *
438  * \return 1 or 0.
439  */
ixmlNode_isAncestor(IXML_Node * ancestorNode,IXML_Node * toFind)440 static int ixmlNode_isAncestor(
441 	/*! [in] The candidate to ancestor \b Node. */
442 	IXML_Node *ancestorNode,
443 	/*! [in] The \b Node to check for an ancestor. */
444 	IXML_Node *toFind)
445 {
446 	int found = 0;
447 
448 	if (ancestorNode != NULL && toFind != NULL) {
449 		if (toFind->parentNode == ancestorNode) {
450 			return 1;
451 		} else {
452 			found = ixmlNode_isAncestor(
453 				ancestorNode->firstChild, toFind);
454 			if (found == 0) {
455 				found = ixmlNode_isAncestor(
456 					ancestorNode->nextSibling, toFind);
457 			}
458 		}
459 	}
460 
461 	return found;
462 }
463 
464 /*!
465  * \brief Check whether toFind is a children of nodeptr.
466  *
467  * \return 1 or 0.
468  */
ixmlNode_isParent(IXML_Node * nodeptr,IXML_Node * toFind)469 static int ixmlNode_isParent(
470 	/*! [in] The candidate to parent \b Node. */
471 	IXML_Node *nodeptr,
472 	/*! [in] The \b Node to check for his parent. */
473 	IXML_Node *toFind)
474 {
475 	int found = 0;
476 
477 	assert(nodeptr != NULL && toFind != NULL);
478 
479 	if (nodeptr != NULL && toFind != NULL)
480 		found = toFind->parentNode == nodeptr;
481 
482 	return found;
483 }
484 
485 /*!
486  * \brief Check to see whether nodeptr allows children of type newChild.
487  *
488  * \return
489  * 	\li 1, if nodeptr can have newChild as children.
490  * 	\li 0, if nodeptr cannot have newChild as children.
491  */
ixmlNode_allowChildren(IXML_Node * nodeptr,IXML_Node * newChild)492 static int ixmlNode_allowChildren(
493 	/*! [in] The \b Node to check. */
494 	IXML_Node *nodeptr,
495 	/*! [in] The child \b Node to check. */
496 	IXML_Node *newChild)
497 {
498 	assert(nodeptr != NULL && newChild != NULL);
499 
500 	switch (nodeptr->nodeType) {
501 	case eATTRIBUTE_NODE:
502 	case eTEXT_NODE:
503 	case eCDATA_SECTION_NODE:
504 		return 0;
505 
506 	case eELEMENT_NODE:
507 		switch (newChild->nodeType) {
508 		case eATTRIBUTE_NODE:
509 		case eDOCUMENT_NODE:
510 			return 0;
511 		default:
512 			break;
513 		}
514 	break;
515 
516 	case eDOCUMENT_NODE:
517 		switch (newChild->nodeType) {
518 		case eELEMENT_NODE:
519 			break;
520 		default:
521 			return 0;
522 		}
523 
524 	default:
525 		break;
526 	}
527 
528 	return 1;
529 }
530 
531 
532 /*!
533  * \brief Compare two nodes to see whether they are the same node.
534  * Parent, sibling and children node are ignored.
535  *
536  * \return
537  * 	\li 1, the two nodes are the same.
538  * 	\li 0, the two nodes are not the same.
539  */
ixmlNode_compare(IXML_Node * srcNode,IXML_Node * destNode)540 int ixmlNode_compare(
541 	/*! [in] The first \b Node. */
542 	IXML_Node *srcNode,
543 	/*! [in] The second \b Node. */
544  	IXML_Node *destNode)
545 {
546 	assert(srcNode != NULL && destNode != NULL);
547 
548 	return
549 		srcNode == destNode ||
550 	(strcmp(srcNode->nodeName, destNode->nodeName) == 0 &&
551 	 strcmp(srcNode->nodeValue, destNode->nodeValue) == 0 &&
552 	 srcNode->nodeType == destNode->nodeType &&
553 	 strcmp(srcNode->namespaceURI, destNode->namespaceURI) == 0 &&
554 	 strcmp(srcNode->prefix, destNode->prefix) == 0 &&
555 	 strcmp(srcNode->localName, destNode->localName) == 0);
556 }
557 
558 
ixmlNode_insertBefore(IXML_Node * nodeptr,IXML_Node * newChild,IXML_Node * refChild)559 int ixmlNode_insertBefore(
560 	IXML_Node *nodeptr,
561 	IXML_Node *newChild,
562 	IXML_Node *refChild)
563 {
564 	int ret = IXML_SUCCESS;
565 
566 	if (nodeptr == NULL || newChild == NULL) {
567 		return IXML_INVALID_PARAMETER;
568 	}
569 	/* whether nodeptr allow children of the type of newChild */
570 	if (ixmlNode_allowChildren(nodeptr, newChild) == 0) {
571 		return IXML_HIERARCHY_REQUEST_ERR;
572 	}
573 	/* or if newChild is one of nodeptr's ancestors */
574 	if (ixmlNode_isAncestor(newChild, nodeptr)) {
575 		return IXML_HIERARCHY_REQUEST_ERR;
576 	}
577 	/* if newChild was created from a different document */
578 	if (nodeptr->ownerDocument != newChild->ownerDocument) {
579 		return IXML_WRONG_DOCUMENT_ERR;
580 	}
581 	/* if refChild is not a child of nodeptr */
582 	if (ixmlNode_isParent(nodeptr, refChild) == 0) {
583 		return IXML_NOT_FOUND_ERR;
584 	}
585 
586 	if (refChild != NULL) {
587 		if (ixmlNode_isParent(nodeptr, newChild)) {
588 			ixmlNode_removeChild(nodeptr, newChild, &newChild);
589 			newChild->nextSibling = NULL;
590 			newChild->prevSibling = NULL;
591 		}
592 		newChild->nextSibling = refChild;
593 		if (refChild->prevSibling != NULL) {
594 			refChild->prevSibling->nextSibling = newChild;
595 			newChild->prevSibling = refChild->prevSibling;
596 		}
597 		refChild->prevSibling = newChild;
598 		if (newChild->prevSibling == NULL) {
599 			nodeptr->firstChild = newChild;
600 		}
601 		newChild->parentNode = nodeptr;
602 	} else {
603 		ret = ixmlNode_appendChild( nodeptr, newChild );
604 	}
605 
606 	return ret;
607 }
608 
609 
ixmlNode_replaceChild(IXML_Node * nodeptr,IXML_Node * newChild,IXML_Node * oldChild,IXML_Node ** returnNode)610 int ixmlNode_replaceChild(
611 	IXML_Node *nodeptr,
612 	IXML_Node *newChild,
613 	IXML_Node *oldChild,
614 	IXML_Node **returnNode)
615 {
616 	int ret = IXML_SUCCESS;
617 
618 	if (nodeptr == NULL || newChild == NULL || oldChild == NULL) {
619 		return IXML_INVALID_PARAMETER;
620 	}
621 	/* if nodetype of nodeptr does not allow children of the type of newChild
622 	 * needs to add later or if newChild is one of nodeptr's ancestors */
623 	if (ixmlNode_isAncestor(newChild, nodeptr)) {
624 		return IXML_HIERARCHY_REQUEST_ERR;
625 	}
626 
627 	if (ixmlNode_allowChildren(nodeptr, newChild) == 0) {
628 		return IXML_HIERARCHY_REQUEST_ERR;
629 	}
630 	/* if newChild was created from a different document */
631 	if (nodeptr->ownerDocument != newChild->ownerDocument) {
632 		return IXML_WRONG_DOCUMENT_ERR;
633 	}
634 	/* if refChild is not a child of nodeptr */
635 	if (ixmlNode_isParent(nodeptr, oldChild) != 1) {
636 		return IXML_NOT_FOUND_ERR;
637 	}
638 
639 	ret = ixmlNode_insertBefore(nodeptr, newChild, oldChild);
640 	if (ret != IXML_SUCCESS) {
641 		return ret;
642 	}
643 
644 	ret = ixmlNode_removeChild(nodeptr, oldChild, returnNode);
645 	return ret;
646 }
647 
648 
ixmlNode_removeChild(IXML_Node * nodeptr,IXML_Node * oldChild,IXML_Node ** returnNode)649 int ixmlNode_removeChild(
650 	IXML_Node *nodeptr,
651 	IXML_Node *oldChild,
652 	IXML_Node **returnNode)
653 {
654 	if (!nodeptr || !oldChild)
655 		return IXML_INVALID_PARAMETER;
656 	if (!ixmlNode_isParent(nodeptr, oldChild))
657 		return IXML_NOT_FOUND_ERR;
658 	if (oldChild->prevSibling)
659 		oldChild->prevSibling->nextSibling = oldChild->nextSibling;
660 	if (nodeptr->firstChild == oldChild)
661 		nodeptr->firstChild = oldChild->nextSibling;
662 	if (oldChild->nextSibling)
663 		oldChild->nextSibling->prevSibling = oldChild->prevSibling;
664 	oldChild->nextSibling = NULL;
665 	oldChild->prevSibling = NULL;
666 	oldChild->parentNode = NULL;
667 	if (returnNode)
668 		*returnNode = oldChild;
669 	else
670 		ixmlNode_free(oldChild);
671 
672 	return IXML_SUCCESS;
673 }
674 
675 
ixmlNode_appendChild(IXML_Node * nodeptr,IXML_Node * newChild)676 int ixmlNode_appendChild(IXML_Node *nodeptr, IXML_Node *newChild)
677 {
678 	IXML_Node *prev = NULL;
679 	IXML_Node *next = NULL;
680 
681 	if (nodeptr == NULL || newChild == NULL) {
682 		return IXML_INVALID_PARAMETER;
683 	}
684 	/* if newChild was created from a different document */
685 	if (newChild->ownerDocument != NULL &&
686 	    nodeptr->ownerDocument != newChild->ownerDocument) {
687 		return IXML_WRONG_DOCUMENT_ERR;
688 	}
689 	/* if newChild is an ancestor of nodeptr */
690 	if (ixmlNode_isAncestor(newChild, nodeptr)) {
691 		return IXML_HIERARCHY_REQUEST_ERR;
692 	}
693 	/* if nodeptr does not allow to have newChild as children */
694 	if (ixmlNode_allowChildren(nodeptr, newChild) == 0) {
695 		return IXML_HIERARCHY_REQUEST_ERR;
696 	}
697 
698 	if (ixmlNode_isParent(nodeptr, newChild)) {
699 		ixmlNode_removeChild(nodeptr, newChild, &newChild);
700 	}
701 	/* set the parent node pointer */
702 	newChild->parentNode = nodeptr;
703 	newChild->ownerDocument = nodeptr->ownerDocument;
704 
705 	/* if the first child */
706 	if (nodeptr->firstChild == NULL) {
707 		nodeptr->firstChild = newChild;
708 	} else {
709 		prev = nodeptr->firstChild;
710 		next = prev->nextSibling;
711 		while (next != NULL) {
712 			prev = next;
713 			next = prev->nextSibling;
714 		}
715 		prev->nextSibling = newChild;
716 		newChild->prevSibling = prev;
717 	}
718 
719 	return IXML_SUCCESS;
720 }
721 
722 /*!
723  * \brief Returns a clone of nodeptr.
724  *
725  * \return A cloned node of nodeptr.
726  */
ixmlNode_cloneTextNode(IXML_Node * nodeptr)727 static IXML_Node *ixmlNode_cloneTextNode(
728 	/*! [in] The \b Node to clone. */
729 	IXML_Node *nodeptr)
730 {
731 	IXML_Node *newNode = NULL;
732 	int rc;
733 
734 	assert(nodeptr != NULL);
735 
736 	newNode = (IXML_Node *)malloc(sizeof (IXML_Node));
737 	if (newNode == NULL) {
738 		return NULL;
739 	} else {
740 		ixmlNode_init(newNode);
741 		rc = ixmlNode_setNodeName(newNode, nodeptr->nodeName);
742 		if (rc != IXML_SUCCESS) {
743 			ixmlNode_free(newNode);
744 			return NULL;
745 		}
746 		rc = ixmlNode_setNodeValue(newNode, nodeptr->nodeValue);
747 		if (rc != IXML_SUCCESS) {
748 			ixmlNode_free(newNode);
749 			return NULL;
750 		}
751 		newNode->nodeType = eTEXT_NODE;
752 	}
753 
754 	return newNode;
755 }
756 
757 /*!
758  * \brief Return a clone of CDATASection node.
759  *
760  * \return A clone of CDATASection node.
761  */
ixmlNode_cloneCDATASect(IXML_CDATASection * nodeptr)762 static IXML_CDATASection *ixmlNode_cloneCDATASect(
763 	/*! [in] The \b Node to clone. */
764 	IXML_CDATASection *nodeptr)
765 {
766 	IXML_CDATASection *newCDATA = NULL;
767 	IXML_Node *newNode;
768 	IXML_Node *srcNode;
769 	int rc;
770 
771 	assert(nodeptr != NULL);
772 	newCDATA = (IXML_CDATASection *)malloc(sizeof (IXML_CDATASection));
773 	if (newCDATA != NULL) {
774 		newNode = (IXML_Node *)newCDATA;
775 		ixmlCDATASection_init(newCDATA);
776 		srcNode = (IXML_Node *)nodeptr;
777 		rc = ixmlNode_setNodeName(newNode, srcNode->nodeName);
778 		if (rc != IXML_SUCCESS) {
779 			ixmlCDATASection_free(newCDATA);
780 			return NULL;
781 		}
782 		rc = ixmlNode_setNodeValue(newNode, srcNode->nodeValue);
783 		if (rc != IXML_SUCCESS) {
784 			ixmlCDATASection_free(newCDATA);
785 			return NULL;
786 		}
787 		newNode->nodeType = eCDATA_SECTION_NODE;
788 	}
789 
790 	return newCDATA;
791 }
792 
793 
794 /*!
795  * \brief Returns a clone of element node.
796  *
797  * \return A clone of element node.
798  */
ixmlNode_cloneElement(IXML_Element * nodeptr)799 static IXML_Element *ixmlNode_cloneElement(
800 	/*! [in] The \b Node to clone. */
801 	IXML_Element *nodeptr)
802 {
803 	IXML_Element *newElement;
804 	IXML_Node *elementNode;
805 	IXML_Node *srcNode;
806 	int rc;
807 
808 	assert(nodeptr != NULL);
809 
810 	newElement = (IXML_Element *)malloc(sizeof (IXML_Element));
811 	if (newElement == NULL) {
812 		return NULL;
813 	}
814 
815 	ixmlElement_init(newElement);
816 	rc = ixmlElement_setTagName(newElement, nodeptr->tagName);
817 	if (rc != IXML_SUCCESS) {
818 		ixmlElement_free(newElement);
819 		return NULL;
820 	}
821 
822 	elementNode = (IXML_Node *)newElement;
823 	srcNode = (IXML_Node *)nodeptr;
824 	rc = ixmlNode_setNodeName(elementNode, srcNode->nodeName);
825 	if (rc != IXML_SUCCESS) {
826 		ixmlElement_free(newElement);
827 		return NULL;
828 	}
829 
830 	rc = ixmlNode_setNodeValue(elementNode, srcNode->nodeValue);
831 	if (rc != IXML_SUCCESS) {
832 		ixmlElement_free(newElement);
833 		return NULL;
834 	}
835 
836 	rc = ixmlNode_setNamespaceURI(elementNode, srcNode->namespaceURI);
837 	if (rc != IXML_SUCCESS) {
838 		ixmlElement_free(newElement);
839 		return NULL;
840 	}
841 
842 	rc = ixmlNode_setPrefix(elementNode, srcNode->prefix);
843 	if (rc != IXML_SUCCESS) {
844 		ixmlElement_free(newElement);
845 		return NULL;
846 	}
847 
848 	rc = ixmlNode_setLocalName(elementNode, srcNode->localName);
849 	if (rc != IXML_SUCCESS) {
850 		ixmlElement_free(newElement);
851 		return NULL;
852 	}
853 
854 	elementNode->nodeType = eELEMENT_NODE;
855 
856 	return newElement;
857 }
858 
859 
860 /*!
861  * \brief Returns a new document node.
862  *
863  * Currently, the IXML_Document struct is just a node, so this function
864  * just mallocs the IXML_Document, sets the node type and name.
865  *
866  * \return A new document node.
867  */
ixmlNode_newDoc(void)868 static IXML_Document *ixmlNode_newDoc(void)
869 {
870 	IXML_Document *newDoc;
871 	IXML_Node *docNode;
872 	int rc;
873 
874 	newDoc = (IXML_Document *)malloc(sizeof (IXML_Document));
875 	if (!newDoc)
876 		return NULL;
877 	ixmlDocument_init(newDoc);
878 	docNode = (IXML_Node *)newDoc;
879 	rc = ixmlNode_setNodeName(docNode, DOCUMENTNODENAME);
880 	if (rc != IXML_SUCCESS) {
881 		ixmlDocument_free(newDoc);
882 		return NULL;
883 	}
884 	newDoc->n.nodeType = eDOCUMENT_NODE;
885 
886 	return newDoc;
887 }
888 
889 /*!
890  * \brief Returns a clone of an attribute node.
891  *
892  * \return A clone of an attribute node.
893  */
ixmlNode_cloneAttr(IXML_Attr * nodeptr)894 static IXML_Attr *ixmlNode_cloneAttr(
895 	/*! [in] The \b Node to clone. */
896 	IXML_Attr *nodeptr)
897 {
898 	IXML_Attr *newAttr;
899 	IXML_Node *attrNode;
900 	IXML_Node *srcNode;
901 	int rc;
902 
903 	assert(nodeptr != NULL);
904 
905 	newAttr = (IXML_Attr *)malloc(sizeof (IXML_Attr));
906 	if (newAttr == NULL) {
907 		return NULL;
908 	}
909 
910 	ixmlAttr_init(newAttr);
911 	attrNode = (IXML_Node *)newAttr;
912 	srcNode = (IXML_Node *)nodeptr;
913 
914 	rc = ixmlNode_setNodeName(attrNode, srcNode->nodeName);
915 	if (rc != IXML_SUCCESS) {
916 		ixmlAttr_free(newAttr);
917 		return NULL;
918 	}
919 
920 	rc = ixmlNode_setNodeValue(attrNode, srcNode->nodeValue);
921 	if (rc != IXML_SUCCESS) {
922 		ixmlAttr_free(newAttr);
923 		return NULL;
924 	}
925 
926 	/* Check to see whether we need to split prefix and localname for attribute */
927 	rc = ixmlNode_setNamespaceURI(attrNode, srcNode->namespaceURI);
928 	if (rc != IXML_SUCCESS) {
929 		ixmlAttr_free(newAttr);
930 		return NULL;
931 	}
932 
933 	rc = ixmlNode_setPrefix(attrNode, srcNode->prefix);
934 	if (rc != IXML_SUCCESS) {
935 		ixmlAttr_free(newAttr);
936 		return NULL;
937 	}
938 
939 	rc = ixmlNode_setLocalName(attrNode, srcNode->localName);
940 	if (rc != IXML_SUCCESS) {
941 		ixmlAttr_free(newAttr);
942 		return NULL;
943 	}
944 
945 	attrNode->nodeType = eATTRIBUTE_NODE;
946 
947 	return newAttr;
948 }
949 
950 /*!
951  * \brief Return a clone of attribute node, with specified field set to 1.
952  *
953  * \return A clone of attribute node, with specified field set to 1.
954  */
ixmlNode_cloneAttrDirect(IXML_Attr * nodeptr)955 static IXML_Attr *ixmlNode_cloneAttrDirect(
956 	/*! [in] The \b Node to clone. */
957 	IXML_Attr *nodeptr)
958 {
959 	IXML_Attr *newAttr;
960 
961 	assert(nodeptr != NULL);
962 
963 	newAttr = ixmlNode_cloneAttr(nodeptr);
964 	if (newAttr != NULL) {
965 		newAttr->specified = 1;
966 	}
967 
968 	return newAttr;
969 }
970 
971 
972 /*!
973  * \brief Sets siblings nodes parent to be the same as this node's.
974  */
ixmlNode_setSiblingNodesParent(IXML_Node * nodeptr)975 static void ixmlNode_setSiblingNodesParent(
976 	/*! [in] The node to operate on. */
977 	IXML_Node *nodeptr)
978 {
979 	IXML_Node *parentNode = nodeptr->parentNode;
980 	IXML_Node *nextptr = nodeptr->nextSibling;
981 
982 	while (nextptr != NULL) {
983 		nextptr->parentNode = parentNode;
984 		nextptr = nextptr->nextSibling;
985 	}
986 }
987 
988 
989 /*!
990  * \brief Recursive function that clones a node tree of nodeptr.
991  *
992  * \returns The cloned node/tree.
993  */
ixmlNode_cloneNodeTreeRecursive(IXML_Node * nodeptr,int deep)994 static IXML_Node *ixmlNode_cloneNodeTreeRecursive(
995 	/*! [in] Node tree to clone. */
996 	IXML_Node *nodeptr,
997 	/*! [in] 1 if you want to clone the tree. */
998 	int deep)
999 {
1000 	IXML_Node *newNode = NULL;
1001 	IXML_Element *newElement = NULL;
1002 	IXML_Attr *newAttr = NULL;
1003 	IXML_CDATASection *newCDATA = NULL;
1004 	IXML_Document *newDoc = NULL;
1005 	IXML_Node *nextSib = NULL;
1006 
1007 	if (nodeptr != NULL) {
1008 		switch (nodeptr->nodeType) {
1009 		case eELEMENT_NODE:
1010 			newElement = ixmlNode_cloneElement((IXML_Element *)nodeptr);
1011 			if (newElement == NULL)
1012 				return NULL;
1013 			newElement->n.firstAttr = ixmlNode_cloneNodeTreeRecursive(
1014 				nodeptr->firstAttr, deep);
1015 			if (deep) {
1016 				newElement->n.firstChild =
1017 					ixmlNode_cloneNodeTreeRecursive(nodeptr->firstChild, deep);
1018 				if (newElement->n.firstChild != NULL) {
1019 					newElement->n.firstChild->parentNode = (IXML_Node *)newElement;
1020 					ixmlNode_setSiblingNodesParent(newElement->n.firstChild);
1021 				}
1022 				nextSib = ixmlNode_cloneNodeTreeRecursive(nodeptr->nextSibling, deep);
1023 				newElement->n.nextSibling = nextSib;
1024 				if (nextSib != NULL) {
1025 					nextSib->prevSibling = (IXML_Node *)newElement;
1026 				}
1027 			}
1028 			newNode = (IXML_Node *)newElement;
1029 			break;
1030 
1031 		case eATTRIBUTE_NODE:
1032 			newAttr = ixmlNode_cloneAttr((IXML_Attr *)nodeptr);
1033 			if (newAttr == NULL)
1034 				return NULL;
1035 			nextSib = ixmlNode_cloneNodeTreeRecursive(nodeptr->nextSibling, deep);
1036 			newAttr->n.nextSibling = nextSib;
1037 			if (nextSib != NULL) {
1038 				nextSib->prevSibling = (IXML_Node *)newAttr;
1039 			}
1040 			newNode = (IXML_Node *)newAttr;
1041 			break;
1042 
1043 		case eTEXT_NODE:
1044 			newNode = ixmlNode_cloneTextNode(nodeptr);
1045 			break;
1046 
1047 		case eCDATA_SECTION_NODE:
1048 			newCDATA = ixmlNode_cloneCDATASect((IXML_CDATASection *)nodeptr);
1049 			newNode = (IXML_Node *)newCDATA;
1050 			break;
1051 
1052 		case eDOCUMENT_NODE:
1053 			newDoc = ixmlNode_newDoc();
1054 			if (newDoc == NULL)
1055 				return NULL;
1056 			newNode = (IXML_Node *)newDoc;
1057 			if (deep) {
1058 				newNode->firstChild = ixmlNode_cloneNodeTreeRecursive(
1059 					nodeptr->firstChild, deep);
1060 				if (newNode->firstChild != NULL) {
1061 					newNode->firstChild->parentNode = newNode;
1062 				}
1063 			}
1064 			break;
1065 
1066 		case eINVALID_NODE:
1067 		case eENTITY_REFERENCE_NODE:
1068 		case eENTITY_NODE:
1069 		case ePROCESSING_INSTRUCTION_NODE:
1070 		case eCOMMENT_NODE:
1071 		case eDOCUMENT_TYPE_NODE:
1072 		case eDOCUMENT_FRAGMENT_NODE:
1073 		case eNOTATION_NODE:
1074 			break;
1075 		}
1076 	}
1077 
1078 	return newNode;
1079 }
1080 
1081 
1082 /*!
1083  * \brief Function that clones a node tree of nodeptr.
1084  *
1085  * \returns The cloned node/tree.
1086  */
ixmlNode_cloneNodeTree(IXML_Node * nodeptr,int deep)1087 static IXML_Node *ixmlNode_cloneNodeTree(
1088 	/*! [in] Node tree to clone. */
1089 	IXML_Node *nodeptr,
1090 	/*! [in] 1 if you want to clone the tree. */
1091 	int deep)
1092 {
1093 	IXML_Node *newNode = NULL;
1094 	IXML_Element *newElement;
1095 	IXML_Node *childNode;
1096 
1097 	assert(nodeptr != NULL);
1098 
1099 	switch (nodeptr->nodeType) {
1100 	case eELEMENT_NODE:
1101 		newElement = ixmlNode_cloneElement((IXML_Element *)nodeptr);
1102 		if (newElement == NULL)
1103 			return NULL;
1104 		newElement->n.firstAttr = ixmlNode_cloneNodeTreeRecursive(nodeptr->firstAttr, deep);
1105 		if (deep) {
1106 			newElement->n.firstChild = ixmlNode_cloneNodeTreeRecursive(
1107 				nodeptr->firstChild, deep);
1108 			childNode = newElement->n.firstChild;
1109 			while (childNode != NULL) {
1110 				childNode->parentNode = (IXML_Node *)newElement;
1111 				childNode = childNode->nextSibling;
1112 			}
1113 			newElement->n.nextSibling = NULL;
1114 		}
1115 		newNode = ( IXML_Node * ) newElement;
1116 		break;
1117 
1118 	case eATTRIBUTE_NODE:
1119 	case eTEXT_NODE:
1120 	case eCDATA_SECTION_NODE:
1121 	case eDOCUMENT_NODE:
1122 		newNode = ixmlNode_cloneNodeTreeRecursive(nodeptr, deep);
1123 		break;
1124 
1125 	case eINVALID_NODE:
1126 	case eENTITY_REFERENCE_NODE:
1127 	case eENTITY_NODE:
1128 	case ePROCESSING_INSTRUCTION_NODE:
1129 	case eCOMMENT_NODE:
1130 	case eDOCUMENT_TYPE_NODE:
1131 	case eDOCUMENT_FRAGMENT_NODE:
1132 	case eNOTATION_NODE:
1133 #if 0
1134 		/* create a new node here? */
1135 		newNode = (IXML_Node *)malloc(sizeof(IXML_Node));
1136 		if (newNode == NULL) {
1137 			return NULL;
1138 		}
1139 #endif
1140 		break;
1141 	}
1142 
1143 	/* by spec, the duplicate node has no parent */
1144 	if (newNode != NULL)
1145 		newNode->parentNode = NULL;
1146 
1147 	return newNode;
1148 }
1149 
1150 
1151 
ixmlNode_cloneNode(IXML_Node * nodeptr,int deep)1152 IXML_Node *ixmlNode_cloneNode(IXML_Node *nodeptr, int deep)
1153 {
1154 	IXML_Node *newNode;
1155 	IXML_Attr *newAttrNode;
1156 
1157 	if (nodeptr == NULL) {
1158 		return NULL;
1159 	}
1160 
1161 	switch (nodeptr->nodeType) {
1162 	case eATTRIBUTE_NODE:
1163 		newAttrNode = ixmlNode_cloneAttrDirect((IXML_Attr *)nodeptr);
1164 		return (IXML_Node *)newAttrNode;
1165 		break;
1166 
1167 	default:
1168 		newNode = ixmlNode_cloneNodeTree(nodeptr, deep);
1169 		return newNode;
1170 		break;
1171 	}
1172 }
1173 
1174 
ixmlNode_getChildNodes(IXML_Node * nodeptr)1175 IXML_NodeList *ixmlNode_getChildNodes(IXML_Node *nodeptr)
1176 {
1177 	IXML_Node *tempNode;
1178 	IXML_NodeList *newNodeList;
1179 	int rc;
1180 
1181 	if (nodeptr == NULL) {
1182 		return NULL;
1183 	}
1184 
1185 	newNodeList = (IXML_NodeList *)malloc(sizeof(IXML_NodeList));
1186 	if (newNodeList == NULL) {
1187 		return NULL;
1188 	}
1189 
1190 	ixmlNodeList_init(newNodeList);
1191 	tempNode = nodeptr->firstChild;
1192 	while (tempNode != NULL) {
1193 		rc = ixmlNodeList_addToNodeList(&newNodeList, tempNode);
1194 		if (rc != IXML_SUCCESS) {
1195 			ixmlNodeList_free(newNodeList);
1196 			return NULL;
1197 		}
1198 
1199 		tempNode = tempNode->nextSibling;
1200 	}
1201 
1202 	return newNodeList;
1203 }
1204 
1205 
ixmlNode_getAttributes(IXML_Node * nodeptr)1206 IXML_NamedNodeMap *ixmlNode_getAttributes(IXML_Node *nodeptr)
1207 {
1208 	IXML_NamedNodeMap *returnNamedNodeMap = NULL;
1209 	IXML_Node *tempNode;
1210 	int rc;
1211 
1212 	if(nodeptr == NULL) {
1213 		return NULL;
1214 	}
1215 
1216 	switch(nodeptr->nodeType) {
1217 	case eELEMENT_NODE:
1218 		returnNamedNodeMap = (IXML_NamedNodeMap *)malloc(sizeof(IXML_NamedNodeMap));
1219 		if(returnNamedNodeMap == NULL) {
1220 			return NULL;
1221 		}
1222 
1223 		ixmlNamedNodeMap_init(returnNamedNodeMap);
1224 		tempNode = nodeptr->firstAttr;
1225 		while( tempNode != NULL ) {
1226 			rc = ixmlNamedNodeMap_addToNamedNodeMap(&returnNamedNodeMap, tempNode);
1227 			if(rc != IXML_SUCCESS) {
1228 				ixmlNamedNodeMap_free(returnNamedNodeMap);
1229 				return NULL;
1230 			}
1231 
1232 			tempNode = tempNode->nextSibling;
1233 		}
1234 		return returnNamedNodeMap;
1235 	default:
1236 		/* if not an ELEMENT_NODE */
1237 		return NULL;
1238 	}
1239 }
1240 
1241 
ixmlNode_hasChildNodes(IXML_Node * nodeptr)1242 int ixmlNode_hasChildNodes(IXML_Node *nodeptr)
1243 {
1244 	if (nodeptr == NULL) {
1245 		return 0;
1246 	}
1247 
1248 	return nodeptr->firstChild != NULL;
1249 }
1250 
1251 
ixmlNode_hasAttributes(IXML_Node * nodeptr)1252 int ixmlNode_hasAttributes(IXML_Node *nodeptr)
1253 {
1254 	if (nodeptr != NULL) {
1255 		switch (nodeptr->nodeType) {
1256 		case eELEMENT_NODE:
1257 			if (nodeptr->firstAttr != NULL)
1258 				return 1;
1259 			break;
1260 		default:
1261 			break;
1262 		}
1263 	}
1264 
1265 	return 0;
1266 }
1267 
1268 
1269 /*!
1270  * \brief Recursively traverse the whole tree, search for element with the
1271  * given tagname.
1272  */
ixmlNode_getElementsByTagNameRecursive(IXML_Node * n,const char * tagname,IXML_NodeList ** list)1273 static void ixmlNode_getElementsByTagNameRecursive(
1274 	/*! [in] The \b Node tree. */
1275 	IXML_Node *n,
1276 	/*! [in] The tag name to match. */
1277 	const char *tagname,
1278 	/*! [out] The output \b NodeList. */
1279 	IXML_NodeList **list)
1280 {
1281 	const char *name;
1282 
1283 	if (n != NULL) {
1284 		if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1285 			name = ixmlNode_getNodeName(n);
1286 			if (strcmp(tagname, name) == 0 || strcmp(tagname, "*") == 0) {
1287 				ixmlNodeList_addToNodeList(list, n);
1288 			}
1289 		}
1290 		ixmlNode_getElementsByTagNameRecursive(ixmlNode_getFirstChild(n), tagname, list);
1291 		ixmlNode_getElementsByTagNameRecursive(ixmlNode_getNextSibling(n), tagname, list);
1292 	}
1293 }
1294 
1295 
ixmlNode_getElementsByTagName(IXML_Node * n,const char * tagname,IXML_NodeList ** list)1296 void ixmlNode_getElementsByTagName(
1297 	IXML_Node *n,
1298 	const char *tagname,
1299 	IXML_NodeList **list)
1300 {
1301 	const char *name;
1302 
1303 	assert(n != NULL && tagname != NULL);
1304 
1305 	if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1306 		name = ixmlNode_getNodeName(n);
1307 		if (strcmp(tagname, name) == 0 || strcmp(tagname, "*") == 0) {
1308 			ixmlNodeList_addToNodeList(list, n);
1309 		}
1310 	}
1311 	ixmlNode_getElementsByTagNameRecursive(ixmlNode_getFirstChild(n), tagname, list);
1312 }
1313 
1314 
1315 /*!
1316  * \brief
1317  */
ixmlNode_getElementsByTagNameNSRecursive(IXML_Node * n,const char * namespaceURI,const char * localName,IXML_NodeList ** list)1318 static void ixmlNode_getElementsByTagNameNSRecursive(
1319 	/*! [in] . */
1320 	IXML_Node *n,
1321 	/*! [in] . */
1322 	const char *namespaceURI,
1323 	/*! [in] . */
1324 	const char *localName,
1325 	/*! [out] . */
1326 	IXML_NodeList **list)
1327 {
1328 	const DOMString nsURI;
1329 	const DOMString name;
1330 
1331 	if (n != NULL) {
1332 		if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1333 			name = ixmlNode_getLocalName(n);
1334 			nsURI = ixmlNode_getNamespaceURI(n);
1335 
1336 			if (name != NULL && nsURI != NULL &&
1337 			    (strcmp(namespaceURI, nsURI) == 0 ||
1338 			     strcmp(namespaceURI, "*") == 0 ) &&
1339 			    (strcmp(name, localName) == 0 ||
1340 			     strcmp(localName, "*") == 0)) {
1341 				ixmlNodeList_addToNodeList(list, n);
1342 			}
1343 		}
1344 		ixmlNode_getElementsByTagNameNSRecursive(
1345 			ixmlNode_getFirstChild(n), namespaceURI, localName, list);
1346 		ixmlNode_getElementsByTagNameNSRecursive(
1347 			ixmlNode_getNextSibling(n), namespaceURI, localName, list);
1348 	}
1349 }
1350 
1351 
ixmlNode_getElementsByTagNameNS(IXML_Node * n,const char * namespaceURI,const char * localName,IXML_NodeList ** list)1352 void ixmlNode_getElementsByTagNameNS(
1353 	IXML_Node *n,
1354 	const char *namespaceURI,
1355 	const char *localName,
1356 	IXML_NodeList **list)
1357 {
1358 	const DOMString nsURI;
1359 	const DOMString name;
1360 
1361 	assert(n != NULL && namespaceURI != NULL && localName != NULL);
1362 
1363 	if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1364 		name = ixmlNode_getLocalName(n);
1365 		nsURI = ixmlNode_getNamespaceURI(n);
1366 		if (name != NULL && nsURI != NULL &&
1367 		    (strcmp(namespaceURI, nsURI) == 0 ||
1368 		     strcmp(namespaceURI, "*") == 0) &&
1369 		    (strcmp(name, localName) == 0 ||
1370 		     strcmp(localName, "*") == 0)) {
1371 			ixmlNodeList_addToNodeList(list, n);
1372 		}
1373 	}
1374 
1375 	ixmlNode_getElementsByTagNameNSRecursive(
1376 		ixmlNode_getFirstChild(n), namespaceURI, localName, list);
1377 }
1378 
1379 
ixmlNode_setNodeName(IXML_Node * node,const DOMString qualifiedName)1380 int ixmlNode_setNodeName(
1381 	IXML_Node *node,
1382 	const DOMString qualifiedName)
1383 {
1384 	int rc = IXML_SUCCESS;
1385 
1386 	assert( node != NULL );
1387 
1388 	if (node->nodeName != NULL) {
1389 		free(node->nodeName);
1390 		node->nodeName = NULL;
1391 	}
1392 
1393 	if (qualifiedName != NULL) {
1394 		/* set the name part */
1395 		node->nodeName = strdup(qualifiedName);
1396 		if (node->nodeName == NULL) {
1397 			return IXML_INSUFFICIENT_MEMORY;
1398 		}
1399 
1400 		rc = Parser_setNodePrefixAndLocalName(node);
1401 		if (rc != IXML_SUCCESS) {
1402 			free(node->nodeName);
1403 		}
1404 	}
1405 
1406 	return rc;
1407 }
1408 
1409 
ixmlNode_setNodeProperties(IXML_Node * destNode,IXML_Node * src)1410 int ixmlNode_setNodeProperties(
1411 	IXML_Node *destNode,
1412 	IXML_Node *src)
1413 {
1414 	int rc;
1415 
1416 	assert(destNode != NULL && src != NULL);
1417 	if(destNode == NULL || src == NULL) {
1418 		return IXML_INVALID_PARAMETER;
1419 	}
1420 
1421 	rc = ixmlNode_setNodeValue(destNode, src->nodeValue);
1422 	if(rc != IXML_SUCCESS) {
1423 		goto ErrorHandler;
1424 	}
1425 
1426 	rc = ixmlNode_setLocalName(destNode, src->localName);
1427 	if(rc != IXML_SUCCESS) {
1428 		goto ErrorHandler;
1429 	}
1430 
1431 	rc = ixmlNode_setPrefix(destNode, src->prefix);
1432 	if(rc != IXML_SUCCESS) {
1433 		goto ErrorHandler;
1434 	}
1435 	/* set nodetype */
1436 	destNode->nodeType = src->nodeType;
1437 
1438 	return IXML_SUCCESS;
1439 
1440 ErrorHandler:
1441 	if(destNode->nodeName != NULL) {
1442 		free(destNode->nodeName);
1443 		destNode->nodeName = NULL;
1444 	}
1445 	if(destNode->nodeValue != NULL) {
1446 		free(destNode->nodeValue);
1447 		destNode->nodeValue = NULL;
1448 	}
1449 	if(destNode->localName != NULL) {
1450 		free(destNode->localName);
1451 		destNode->localName = NULL;
1452 	}
1453 
1454 	return IXML_INSUFFICIENT_MEMORY;
1455 }
1456 
1457 #ifdef IXML_HAVE_SCRIPTSUPPORT
ixmlNode_setCTag(IXML_Node * nodeptr,void * ctag)1458 void ixmlNode_setCTag(IXML_Node *nodeptr, void *ctag)
1459 {
1460 	if (nodeptr != NULL) nodeptr->ctag = ctag;
1461 }
1462 
ixmlNode_getCTag(IXML_Node * nodeptr)1463 void* ixmlNode_getCTag(IXML_Node *nodeptr)
1464 {
1465 	if (nodeptr != NULL)
1466 		return nodeptr->ctag;
1467 	else
1468 		return NULL;
1469 }
1470 #endif
1471