1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
30 
31 #include "xmldocumentwrapper_xmlsecimpl.hxx"
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 
34 #include <xmloff/attrlist.hxx>
35 #include "xmlelementwrapper_xmlsecimpl.hxx"
36 
37 //#include <malloc.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 /*
43  * Deleted by AF
44 #include <memory.h>
45  */
46 
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 
50 #ifndef INCLUDED_VECTOR
51 #include <vector>
52 #define INCLUDED_VECTOR
53 #endif
54 
55 #ifdef UNX
56 #define stricmp strcasecmp
57 #endif
58 
59 namespace cssu = com::sun::star::uno;
60 namespace cssl = com::sun::star::lang;
61 namespace cssxc = com::sun::star::xml::crypto;
62 namespace cssxcsax = com::sun::star::xml::csax;
63 namespace cssxs = com::sun::star::xml::sax;
64 namespace cssxw = com::sun::star::xml::wrapper;
65 
66 #define SERVICE_NAME "com.sun.star.xml.wrapper.XMLDocumentWrapper"
67 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.XMLDocumentWrapper_XmlSecImpl"
68 
69 #define STRXMLNS "xmlns"
70 
71 #define RTL_ASCII_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_ASCII_US
72 #define RTL_UTF8_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_UTF8
73 
74 /* used by the recursiveDelete method */
75 #define NODE_REMOVED    0
76 #define NODE_NOTREMOVED 1
77 #define NODE_STOPED     2
78 
79 XMLDocumentWrapper_XmlSecImpl::XMLDocumentWrapper_XmlSecImpl( )
80 {
81 	saxHelper.startDocument();
82 	m_pDocument = saxHelper.getDocument();
83 
84 	/*
85 	 * creates the virtual root element
86 	 */
87 	saxHelper.startElement(rtl::OUString(RTL_UTF8_USTRINGPARAM( "root" )), cssu::Sequence<cssxcsax::XMLAttribute>());
88 
89 	m_pRootElement = saxHelper.getCurrentNode();
90 	m_pCurrentElement = m_pRootElement;
91 }
92 
93 XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl()
94 {
95 	saxHelper.endDocument();
96 	xmlFreeDoc(m_pDocument);
97 }
98 
99 void XMLDocumentWrapper_XmlSecImpl::getNextSAXEvent()
100 /****** XMLDocumentWrapper_XmlSecImpl/getNextSAXEvent *************************
101  *
102  *   NAME
103  *	getNextSAXEvent -- Prepares the next SAX event to be manipulate
104  *
105  *   SYNOPSIS
106  *	getNextSAXEvent();
107  *
108  *   FUNCTION
109  *	When converting the document into SAX events, this method is used to
110  *	decide the next SAX event to be generated.
111  *	Two member variables are checked to make the decision, the
112  *	m_pCurrentElement and the m_nCurrentPosition.
113  *	The m_pCurrentElement represents the node which have been covered, and
114  *	the m_nCurrentPosition represents the event which have been sent.
115  *	For example, suppose that the m_pCurrentElement
116  *	points to element A, and the m_nCurrentPosition equals to
117  *	NODEPOSITION_STARTELEMENT, then the next SAX event should be the
118  *	endElement for element A if A has no child, or startElement for the
119  *	first child element of element A otherwise.
120  *	The m_nCurrentPosition can be one of following values:
121  *	NODEPOSITION_STARTELEMENT for startElement;
122  *	NODEPOSITION_ENDELEMENT for endElement;
123  *	NODEPOSITION_NORMAL for other SAX events;
124  *
125  *   INPUTS
126  *	empty
127  *
128  *   RESULT
129  *	empty
130  *
131  *   HISTORY
132  *	05.01.2004 -	implemented
133  *
134  *   AUTHOR
135  *	Michael Mi
136  *	Email: michael.mi@sun.com
137  ******************************************************************************/
138 {
139 	OSL_ASSERT( m_pCurrentElement != NULL );
140 
141         /*
142          * Get the next event through tree order.
143          *
144          * if the current event is a startElement, then the next
145          * event depends on whether or not the current node has
146          * children.
147          */
148 	if (m_nCurrentPosition == NODEPOSITION_STARTELEMENT)
149 	{
150 	        /*
151 	         * If the current node has children, then its first child
152 	         * should be next current node, and the next event will be
153 	         * startElement or charaters(PI) based on that child's node
154 	         * type. Otherwise, the endElement of current node is the
155 	         * next event.
156 	         */
157 		if (m_pCurrentElement->children != NULL)
158 		{
159 			m_pCurrentElement = m_pCurrentElement->children;
160 			m_nCurrentPosition
161 				= (m_pCurrentElement->type == XML_ELEMENT_NODE)?
162 					NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL;
163 		}
164 		else
165 		{
166 			m_nCurrentPosition = NODEPOSITION_ENDELEMENT;
167 		}
168 	}
169         /*
170          * if the current event is a not startElement, then the next
171          * event depends on whether or not the current node has
172          * following sibling.
173          */
174 	else if (m_nCurrentPosition == NODEPOSITION_ENDELEMENT || m_nCurrentPosition == NODEPOSITION_NORMAL)
175 	{
176 		xmlNodePtr pNextSibling = m_pCurrentElement->next;
177 
178 	        /*
179 	         * If the current node has following sibling, that sibling
180 	         * should be next current node, and the next event will be
181 	         * startElement or charaters(PI) based on that sibling's node
182 	         * type. Otherwise, the endElement of current node's parent
183 	         * becomes the next event.
184 	         */
185 		if (pNextSibling != NULL)
186 		{
187 			m_pCurrentElement = pNextSibling;
188 			m_nCurrentPosition
189 				= (m_pCurrentElement->type == XML_ELEMENT_NODE)?
190 					NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL;
191 		}
192 		else
193 		{
194 			m_pCurrentElement = m_pCurrentElement->parent;
195 			m_nCurrentPosition = NODEPOSITION_ENDELEMENT;
196 		}
197 	}
198 }
199 
200 void XMLDocumentWrapper_XmlSecImpl::sendStartElement(
201 	const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
202 	const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
203 	const xmlNodePtr pNode) const
204 	throw (cssxs::SAXException)
205 /****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************
206  *
207  *   NAME
208  *	sendStartElement -- Constructs a startElement SAX event
209  *
210  *   SYNOPSIS
211  *	sendStartElement(xHandler, xHandler2, pNode);
212  *
213  *   FUNCTION
214  *	Used when converting the document into SAX event stream.
215  *	This method constructs a startElement SAX event for a particular
216  *	element, then calls the startElement methods of the XDocumentHandlers.
217  *
218  *   INPUTS
219  *	xHandler -	the first XDocumentHandler interface to receive the
220  *			startElement SAX event. It can be NULL.
221  *	xHandler2 -	the second XDocumentHandler interface to receive the
222  *			startElement SAX event. It can't be NULL.
223  *	pNode -		the node on which the startElement should be generated.
224  *			This node must be a element type.
225  *
226  *   RESULT
227  *	empty
228  *
229  *   HISTORY
230  *	05.01.2004 -	implemented
231  *
232  *   AUTHOR
233  *	Michael Mi
234  *	Email: michael.mi@sun.com
235  ******************************************************************************/
236 {
237 	SvXMLAttributeList* pAttributeList = new SvXMLAttributeList();
238 	cssu::Reference < cssxs::XAttributeList > xAttrList = cssu::Reference< cssxs::XAttributeList > (pAttributeList);
239 
240 	xmlNsPtr pNsDef = pNode->nsDef;
241 
242 	while (pNsDef != NULL)
243 	{
244 		const xmlChar* pNsPrefix = pNsDef->prefix;
245 		const xmlChar* pNsHref = pNsDef->href;
246 
247 		if (pNsDef->prefix == NULL)
248 		{
249 			pAttributeList->AddAttribute(
250 				rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )),
251 				rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref )));
252 		}
253 		else
254 		{
255 			pAttributeList->AddAttribute(
256 				rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS ))
257 				+rtl::OUString(RTL_UTF8_USTRINGPARAM( ":" ))
258 				+rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsPrefix )),
259 				rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref )));
260 		}
261 
262 		pNsDef = pNsDef->next;
263 	}
264 
265 	xmlAttrPtr pAttr = pNode->properties;
266 
267 	while (pAttr != NULL)
268 	{
269 		const xmlChar* pAttrName = pAttr->name;
270 		xmlNsPtr pAttrNs = pAttr->ns;
271 
272 		rtl::OUString ouAttrName;
273 		if (pAttrNs == NULL)
274 		{
275 			ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName ));
276 		}
277 		else
278 		{
279 			ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrNs->prefix))
280 				+rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)":" ))
281 				+rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName ));
282 		}
283 
284 		pAttributeList->AddAttribute(
285 			ouAttrName,
286 			rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)(pAttr->children->content))));
287 		pAttr = pAttr->next;
288 	}
289 
290 	rtl::OString sNodeName = getNodeQName(pNode);
291 
292 	if (xHandler.is())
293 	{
294 		xHandler->startElement(
295 			rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )),
296 			xAttrList);
297 	}
298 
299 	xHandler2->startElement(
300 		rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )),
301 		xAttrList);
302 }
303 
304 void XMLDocumentWrapper_XmlSecImpl::sendEndElement(
305 	const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
306 	const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
307 	const xmlNodePtr pNode) const
308 	throw (cssxs::SAXException)
309 /****** XMLDocumentWrapper_XmlSecImpl/sendEndElement **************************
310  *
311  *   NAME
312  *	sendEndElement -- Constructs a endElement SAX event
313  *
314  *   SYNOPSIS
315  *	sendEndElement(xHandler, xHandler2, pNode);
316  *
317  *   FUNCTION
318  *	Used when converting the document into SAX event stream.
319  *	This method constructs a endElement SAX event for a particular
320  *	element, then calls the endElement methods of the XDocumentHandlers.
321  *
322  *   INPUTS
323  *	xHandler -	the first XDocumentHandler interface to receive the
324  *			endElement SAX event. It can be NULL.
325  *	xHandler2 -	the second XDocumentHandler interface to receive the
326  *			endElement SAX event. It can't be NULL.
327  *	pNode -		the node on which the endElement should be generated.
328  *			This node must be a element type.
329  *
330  *   RESULT
331  *	empty
332  *
333  *   HISTORY
334  *	05.01.2004 -	implemented
335  *
336  *   AUTHOR
337  *	Michael Mi
338  *	Email: michael.mi@sun.com
339  ******************************************************************************/
340 {
341 	rtl::OString sNodeName = getNodeQName(pNode);
342 
343 	if (xHandler.is())
344 	{
345 		xHandler->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )));
346 	}
347 
348 	xHandler2->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )));
349 }
350 
351 void XMLDocumentWrapper_XmlSecImpl::sendNode(
352 	const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
353 	const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
354 	const xmlNodePtr pNode) const
355 	throw (cssxs::SAXException)
356 /****** XMLDocumentWrapper_XmlSecImpl/sendNode ********************************
357  *
358  *   NAME
359  *	sendNode -- Constructs a characters SAX event or a
360  *	processingInstruction SAX event
361  *
362  *   SYNOPSIS
363  *	sendNode(xHandler, xHandler2, pNode);
364  *
365  *   FUNCTION
366  *	Used when converting the document into SAX event stream.
367  *	This method constructs a characters SAX event or a
368  *	processingInstructionfor SAX event based on the type of a particular
369  *	element, then calls the corresponding methods of the XDocumentHandlers.
370  *
371  *   INPUTS
372  *	xHandler -	the first XDocumentHandler interface to receive the
373  *			SAX event. It can be NULL.
374  *	xHandler2 -	the second XDocumentHandler interface to receive the
375  *			SAX event. It can't be NULL.
376  *	pNode -		the node on which the endElement should be generated.
377  *			If it is a text node, then a characters SAX event is
378  *			generated; if it is a PI node, then a
379  *			processingInstructionfor SAX event is generated.
380  *
381  *   RESULT
382  *	empty
383  *
384  *   HISTORY
385  *	05.01.2004 -	implemented
386  *
387  *   AUTHOR
388  *	Michael Mi
389  *	Email: michael.mi@sun.com
390  ******************************************************************************/
391 {
392 	xmlElementType type = pNode->type;
393 
394 	if (type == XML_TEXT_NODE)
395 	{
396 		if (xHandler.is())
397 		{
398 			xHandler->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
399 		}
400 
401 		xHandler2->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
402 	}
403 	else if (type == XML_PI_NODE)
404 	{
405 		if (xHandler.is())
406 		{
407 			xHandler->processingInstruction(
408 				rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )),
409 				rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
410 		}
411 
412 		xHandler2->processingInstruction(
413 			rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )),
414 			rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
415 	}
416 }
417 
418 rtl::OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode) const
419 /****** XMLDocumentWrapper_XmlSecImpl/getNodeQName ****************************
420  *
421  *   NAME
422  *	getNodeQName -- Retrives the qualified name of a node
423  *
424  *   SYNOPSIS
425  *	name = getNodeQName(pNode);
426  *
427  *   FUNCTION
428  *	see NAME
429  *
430  *   INPUTS
431  *	pNode -	the node whose name will be retrived
432  *
433  *   RESULT
434  *	name - the node's qualified name
435  *
436  *   HISTORY
437  *	05.01.2004 -	implemented
438  *
439  *   AUTHOR
440  *	Michael Mi
441  *	Email: michael.mi@sun.com
442  ******************************************************************************/
443 {
444 	rtl::OString sNodeName((const sal_Char*)pNode->name);
445 	if (pNode->ns != NULL)
446 	{
447 		xmlNsPtr pNs = pNode->ns;
448 
449 		if (pNs->prefix != NULL)
450 		{
451 			rtl::OString sPrefix((const sal_Char*)pNs->prefix);
452 			sNodeName = sPrefix+rtl::OString(":")+sNodeName;
453 		}
454 	}
455 
456 	return sNodeName;
457 }
458 
459 xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const cssu::Reference< cssxw::XXMLElementWrapper >& xXMLElement) const
460 /****** XMLDocumentWrapper_XmlSecImpl/checkElement ****************************
461  *
462  *   NAME
463  *	checkElement -- Retrives the node wrapped by an XXMLElementWrapper
464  *	interface
465  *
466  *   SYNOPSIS
467  *	node = checkElement(xXMLElement);
468  *
469  *   FUNCTION
470  *	see NAME
471  *
472  *   INPUTS
473  *	xXMLElement -	the XXMLElementWrapper interface wraping a node
474  *
475  *   RESULT
476  *	node - the node wrapped in the XXMLElementWrapper interface
477  *
478  *   HISTORY
479  *	05.01.2004 -	implemented
480  *
481  *   AUTHOR
482  *	Michael Mi
483  *	Email: michael.mi@sun.com
484  ******************************************************************************/
485 {
486 	xmlNodePtr rc = NULL;
487 
488 	if (xXMLElement.is())
489 	{
490 		cssu::Reference< cssl::XUnoTunnel > xNodTunnel( xXMLElement, cssu::UNO_QUERY ) ;
491 		if( !xNodTunnel.is() )
492 		{
493 			throw cssu::RuntimeException() ;
494 		}
495 
496 		XMLElementWrapper_XmlSecImpl* pElement
497 			= reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
498                 sal::static_int_cast<sal_uIntPtr>(
499                     xNodTunnel->getSomething(
500                         XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ))) ;
501 
502 		if( pElement == NULL ) {
503 			throw cssu::RuntimeException() ;
504 		}
505 
506 		rc = pElement->getNativeElement();
507 	}
508 
509 	return rc;
510 }
511 
512 sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete(
513 	const xmlNodePtr pNode)
514 /****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete *************************
515  *
516  *   NAME
517  *	recursiveDelete -- Deletes a paticular node with its branch.
518  *
519  *   SYNOPSIS
520  *	result = recursiveDelete(pNode);
521  *
522  *   FUNCTION
523  *	Deletes a paticular node with its branch, while reserving the nodes
524  *	(and their brance) listed in the m_aReservedNodes.
525  *	The deletion process is preformed in the tree order, that is, a node
526  *	is deleted after its previous sibling node is deleted, a parent node
527  *	is deleted after its branch is deleted.
528  *	During the deletion process when the m_pStopAtNode is reached, the
529  *	progress is interrupted at once.
530  *
531  *   INPUTS
532  *	pNode -	the node to be deleted
533  *
534  *   RESULT
535  *	result -	the result of the deletion process, can be one of following
536  *			values:
537  *			NODE_STOPED - the process is interrupted by meeting the
538  *				m_pStopAtNode
539  *			NODE_NOTREMOVED - the pNode is not completely removed
540  *				because there is its descendant in the
541  *				m_aReservedNodes list
542  *			NODE_REMOVED - the pNode and its branch are completely
543  *				removed
544  *
545  *   NOTES
546  *	The node in the m_aReservedNodes list must be in the tree order, otherwise
547  *	the result is unpredictable.
548  *
549  *   HISTORY
550  *	05.01.2004 -	implemented
551  *
552  *   AUTHOR
553  *	Michael Mi
554  *	Email: michael.mi@sun.com
555  ******************************************************************************/
556 {
557 	if (pNode == m_pStopAtNode)
558 	{
559 		return NODE_STOPED;
560 	}
561 
562 	if (pNode != m_pCurrentReservedNode)
563 	{
564 		xmlNodePtr pChild = pNode->children;
565 
566 		xmlNodePtr pNextSibling;
567 		bool bIsRemoved = true;
568 		sal_Int32 nResult;
569 
570 		while( pChild != NULL )
571 		{
572 			pNextSibling = pChild->next;
573 			nResult = recursiveDelete(pChild);
574 
575 			switch (nResult)
576 			{
577 			case NODE_STOPED:
578 				return NODE_STOPED;
579 			case NODE_NOTREMOVED:
580 				bIsRemoved = false;
581 				break;
582 			case NODE_REMOVED:
583 				removeNode(pChild);
584 				break;
585 			default:
586 				throw cssu::RuntimeException();
587 			}
588 
589 			pChild = pNextSibling;
590 		}
591 
592 		if (pNode == m_pCurrentElement)
593 		{
594 			bIsRemoved = false;
595 		}
596 
597 		return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED;
598 	}
599 	else
600 	{
601 		getNextReservedNode();
602 		return NODE_NOTREMOVED;
603 	}
604 }
605 
606 void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode()
607 /****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode *********************
608  *
609  *   NAME
610  *	getNextReservedNode -- Highlights the next reserved node in the
611  *	reserved node list
612  *
613  *   SYNOPSIS
614  *	getNextReservedNode();
615  *
616  *   FUNCTION
617  *	The m_aReservedNodes array holds a node list, while the
618  *	m_pCurrentReservedNode points to the one currently highlighted.
619  *	This method is used to highlight the next node in the node list.
620  *	This method is called at the time when the current highlighted node
621  *	has been already processed, and the next node should be ready.
622  *
623  *   INPUTS
624  *	empty
625  *
626  *   RESULT
627  *	empty
628  *
629  *   HISTORY
630  *	05.01.2004 -	implemented
631  *
632  *   AUTHOR
633  *	Michael Mi
634  *	Email: michael.mi@sun.com
635  ******************************************************************************/
636 {
637 	if (m_nReservedNodeIndex < m_aReservedNodes.getLength())
638 	{
639 		m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] );
640 		m_nReservedNodeIndex ++;
641 	}
642 	else
643 	{
644 		m_pCurrentReservedNode = NULL;
645 	}
646 }
647 
648 void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const
649 /****** XMLDocumentWrapper_XmlSecImpl/removeNode ******************************
650  *
651  *   NAME
652  *	removeNode -- Deletes a node with its branch unconditionaly
653  *
654  *   SYNOPSIS
655  *	removeNode( pNode );
656  *
657  *   FUNCTION
658  *	Delete the node along with its branch from the document.
659  *
660  *   INPUTS
661  *	pNode -	the node to be deleted
662  *
663  *   RESULT
664  *	empty
665  *
666  *   HISTORY
667  *	05.01.2004 -	implemented
668  *
669  *   AUTHOR
670  *	Michael Mi
671  *	Email: michael.mi@sun.com
672  ******************************************************************************/
673 {
674 	/* you can't remove the current node */
675 	OSL_ASSERT( m_pCurrentElement != pNode );
676 
677 	xmlAttrPtr pAttr = pNode->properties;
678 
679 	while (pAttr != NULL)
680 	{
681 		if (!stricmp((sal_Char*)pAttr->name,"id"))
682 		{
683 			xmlRemoveID(m_pDocument, pAttr);
684 		}
685 
686 		pAttr = pAttr->next;
687 	}
688 
689 	xmlUnlinkNode(pNode);
690 	xmlFreeNode(pNode);
691 }
692 
693 void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const
694 /****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr *****************************
695  *
696  *   NAME
697  *	buildIDAttr -- build the ID attribute of a node
698  *
699  *   SYNOPSIS
700  *	buildIDAttr( pNode );
701  *
702  *   FUNCTION
703  *	see NAME
704  *
705  *   INPUTS
706  *	pNode -	the node whose id attribute will be built
707  *
708  *   RESULT
709  *	empty
710  *
711  *   HISTORY
712  *	14.06.2004 -	implemented
713  *
714  *   AUTHOR
715  *	Michael Mi
716  *	Email: michael.mi@sun.com
717  ******************************************************************************/
718 {
719 	xmlAttrPtr idAttr = xmlHasProp( pNode, (const unsigned char *)"id" );
720 	if (idAttr == NULL)
721 	{
722 		idAttr = xmlHasProp( pNode, (const unsigned char *)"Id" );
723 	}
724 
725 	if (idAttr != NULL)
726 	{
727 		xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ;
728 		xmlAddID( NULL, m_pDocument, idValue, idAttr );
729 	}
730 }
731 
732 void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const
733 /****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink ***************************
734  *
735  *   NAME
736  *	rebuildIDLink -- rebuild the ID link for the branch
737  *
738  *   SYNOPSIS
739  *	rebuildIDLink( pNode );
740  *
741  *   FUNCTION
742  *	see NAME
743  *
744  *   INPUTS
745  *	pNode -	the node, from which the branch will be rebuilt
746  *
747  *   RESULT
748  *	empty
749  *
750  *   HISTORY
751  *	14.06.2004 -	implemented
752  *
753  *   AUTHOR
754  *	Michael Mi
755  *	Email: michael.mi@sun.com
756  ******************************************************************************/
757 {
758 	if (pNode != NULL && pNode->type == XML_ELEMENT_NODE)
759 	{
760 		buildIDAttr( pNode );
761 
762 		xmlNodePtr child = pNode->children;
763 		while (child != NULL)
764 		{
765 			rebuildIDLink(child);
766 			child = child->next;
767 		}
768 	}
769 }
770 
771 /* XXMLDocumentWrapper */
772 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement(  )
773 	throw (cssu::RuntimeException)
774 {
775 	XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement);
776 	return (cssu::Reference< cssxw::XXMLElementWrapper >)pElement;
777 }
778 
779 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const cssu::Reference< cssxw::XXMLElementWrapper >& element )
780 	throw (cssu::RuntimeException)
781 {
782 	m_pCurrentElement = checkElement( element );
783 	saxHelper.setCurrentNode( m_pCurrentElement );
784 }
785 
786 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement(  )
787 	throw (cssu::RuntimeException)
788 {
789 	OSL_ASSERT( m_pCurrentElement != NULL );
790 
791 	xmlNodePtr pOldCurrentElement = m_pCurrentElement;
792 
793 	/*
794 	 * pop the top node in the parser context's
795 	 * nodeTab stack, then the parent of that node will
796 	 * automatically become the new stack top, and
797 	 * the current node as well.
798 	 */
799 	saxHelper.endElement(
800 		rtl::OUString(
801 			RTL_UTF8_USTRINGPARAM (
802 				(sal_Char*)(pOldCurrentElement->name)
803 			)));
804 	m_pCurrentElement = saxHelper.getCurrentNode();
805 
806 	/*
807 	 * remove the node
808 	 */
809 	removeNode(pOldCurrentElement);
810 }
811 
812 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
813 	throw (cssu::RuntimeException)
814 {
815 	xmlNodePtr pNode = checkElement(node);
816 	return (pNode == m_pCurrentElement);
817 }
818 
819 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty(  )
820 	throw (cssu::RuntimeException)
821 {
822 	sal_Bool rc = sal_False;
823 
824 	if (m_pCurrentElement->children == NULL)
825 	{
826 		rc = sal_True;
827 	}
828 
829 	return rc;
830 }
831 
832 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
833 	throw (cssu::RuntimeException)
834 {
835 	xmlNodePtr pNode = checkElement(node);
836 	return rtl::OUString(RTL_UTF8_USTRINGPARAM ( (sal_Char*)pNode->name ));
837 }
838 
839 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData(
840 	const cssu::Reference< cssxw::XXMLElementWrapper >& node,
841 	const cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >& reservedDescendants,
842 	const cssu::Reference< cssxw::XXMLElementWrapper >& stopAtNode )
843 	throw (cssu::RuntimeException)
844 {
845 	xmlNodePtr pTargetNode = checkElement(node);
846 
847 	m_pStopAtNode = checkElement(stopAtNode);
848 	m_aReservedNodes = reservedDescendants;
849 	m_nReservedNodeIndex = 0;
850 
851 	getNextReservedNode();
852 
853 	recursiveDelete(pTargetNode);
854 }
855 
856 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
857 	throw (cssu::RuntimeException)
858 {
859 	xmlNodePtr pTargetNode = checkElement(node);
860 	xmlNodePtr pParent;
861 
862 	while (pTargetNode != NULL)
863 	{
864 		if (pTargetNode->children != NULL || pTargetNode == m_pCurrentElement)
865 		{
866 			break;
867 		}
868 
869 		pParent = pTargetNode->parent;
870 		removeNode(pTargetNode);
871 		pTargetNode = pParent;
872 	}
873 }
874 
875 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const cssu::Reference< cssxs::XDocumentHandler >& handler )
876 	throw (cssxs::SAXException, cssu::RuntimeException)
877 {
878 	if (m_pRootElement != NULL)
879 	{
880 		xmlNodePtr pTempCurrentElement = m_pCurrentElement;
881 		sal_Int32 nTempCurrentPosition = m_nCurrentPosition;
882 
883 		m_pCurrentElement = m_pRootElement;
884 
885 		m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
886 		cssu::Reference< cssxs::XDocumentHandler > xHandler = handler;
887 
888 		while(true)
889 		{
890 			switch (m_nCurrentPosition)
891 			{
892 			case NODEPOSITION_STARTELEMENT:
893 				sendStartElement(NULL, xHandler, m_pCurrentElement);
894 				break;
895 			case NODEPOSITION_ENDELEMENT:
896 				sendEndElement(NULL, xHandler, m_pCurrentElement);
897 				break;
898 			case NODEPOSITION_NORMAL:
899 				sendNode(NULL, xHandler, m_pCurrentElement);
900 				break;
901 			}
902 
903 			if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT ))
904 			{
905 				break;
906 			}
907 
908 			getNextSAXEvent();
909 		}
910 
911 		m_pCurrentElement = pTempCurrentElement;
912 		m_nCurrentPosition = nTempCurrentPosition;
913 	}
914 }
915 
916 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents(
917 	const cssu::Reference< cssxs::XDocumentHandler >& handler,
918 	const cssu::Reference< cssxs::XDocumentHandler >& xEventKeeperHandler,
919 	const cssu::Reference< cssxw::XXMLElementWrapper >& startNode,
920 	const cssu::Reference< cssxw::XXMLElementWrapper >& endNode )
921 	throw (cssxs::SAXException, cssu::RuntimeException)
922 {
923         /*
924          * The first SAX event is the startElement of the startNode
925          * element.
926          */
927 	bool bHasCurrentElementChild = (m_pCurrentElement->children != NULL);
928 
929 	xmlNodePtr pTempCurrentElement = m_pCurrentElement;
930 
931 	m_pCurrentElement = checkElement(startNode);
932 
933 	if (m_pCurrentElement->type == XML_ELEMENT_NODE)
934 	{
935 		m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
936 	}
937 	else
938 	{
939 		m_nCurrentPosition = NODEPOSITION_NORMAL;
940 	}
941 
942 	xmlNodePtr pEndNode = checkElement(endNode);
943 
944 	cssu::Reference < cssxc::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, cssu::UNO_QUERY );
945 
946 	cssu::Reference< cssxs::XDocumentHandler > xHandler = handler;
947 
948 	while(true)
949 	{
950 		switch (m_nCurrentPosition)
951 		{
952 		case NODEPOSITION_STARTELEMENT:
953 			sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
954 			break;
955 		case NODEPOSITION_ENDELEMENT:
956 			sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
957 			break;
958 		case NODEPOSITION_NORMAL:
959 			sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement);
960 			break;
961 		default:
962 			throw cssu::RuntimeException();
963 		}
964 
965 		if (xSAXEventKeeper->isBlocking())
966 		{
967 			xHandler = NULL;
968 		}
969 
970 		if (pEndNode == NULL &&
971 			((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) ||
972 			 (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT)))
973 		{
974 			break;
975 		}
976 
977 		getNextSAXEvent();
978 
979 	        /*
980 	         * If there is an end point specified, then check whether
981 	         * the current node equals to the end point. If so, stop
982 	         * generating.
983 	         */
984 		if (pEndNode != NULL && m_pCurrentElement == pEndNode)
985 		{
986 			break;
987 		}
988 	}
989 
990 	m_pCurrentElement = pTempCurrentElement;
991 }
992 
993 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(
994 	const com::sun::star::uno::Reference< com::sun::star::xml::wrapper::XXMLElementWrapper >& node )
995 	throw (com::sun::star::uno::RuntimeException)
996 {
997 	xmlNodePtr pNode = checkElement( node );
998 	rebuildIDLink(pNode);
999 }
1000 
1001 
1002 /* cssxs::XDocumentHandler */
1003 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument(  )
1004 	throw (cssxs::SAXException, cssu::RuntimeException)
1005 {
1006 }
1007 
1008 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument(  )
1009 	throw (cssxs::SAXException, cssu::RuntimeException)
1010 {
1011 }
1012 
1013 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const rtl::OUString& aName, const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1014 	throw (cssxs::SAXException, cssu::RuntimeException)
1015 {
1016 	sal_Int32 nLength = xAttribs->getLength();
1017 	cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1018 
1019 	for (int i = 0; i < nLength; ++i)
1020 	{
1021 		aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1022 		aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1023 	}
1024 
1025 	_startElement(aName, aAttributes);
1026 }
1027 
1028 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const rtl::OUString& aName )
1029 	throw (cssxs::SAXException, cssu::RuntimeException)
1030 {
1031 	saxHelper.endElement(aName);
1032 	m_pCurrentElement = saxHelper.getCurrentNode();
1033 }
1034 
1035 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars )
1036 	throw (cssxs::SAXException, cssu::RuntimeException)
1037 {
1038 	saxHelper.characters(aChars);
1039 }
1040 
1041 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1042 	throw (cssxs::SAXException, cssu::RuntimeException)
1043 {
1044 	saxHelper.ignorableWhitespace(aWhitespaces);
1045 }
1046 
1047 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
1048 	throw (cssxs::SAXException, cssu::RuntimeException)
1049 {
1050 	saxHelper.processingInstruction(aTarget, aData);
1051 }
1052 
1053 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator )
1054 	throw (cssxs::SAXException, cssu::RuntimeException)
1055 {
1056 	saxHelper.setDocumentLocator(xLocator);
1057 }
1058 
1059 /* XCompressedDocumentHandler */
1060 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument(  )
1061 	throw (cssxs::SAXException, cssu::RuntimeException)
1062 {
1063 }
1064 
1065 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument(  )
1066 	throw (cssxs::SAXException, cssu::RuntimeException)
1067 {
1068 }
1069 
1070 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startElement( const rtl::OUString& aName, const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
1071 	throw (cssxs::SAXException, cssu::RuntimeException)
1072 {
1073 	saxHelper.startElement(aName, aAttributes);
1074 	m_pCurrentElement = saxHelper.getCurrentNode();
1075 
1076 	buildIDAttr( m_pCurrentElement );
1077 }
1078 
1079 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName )
1080 	throw (cssxs::SAXException, cssu::RuntimeException)
1081 {
1082 	endElement( aName );
1083 }
1084 
1085 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars )
1086 	throw (cssxs::SAXException, cssu::RuntimeException)
1087 {
1088 	characters( aChars );
1089 }
1090 
1091 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces )
1092 	throw (cssxs::SAXException, cssu::RuntimeException)
1093 {
1094 	ignorableWhitespace( aWhitespaces );
1095 }
1096 
1097 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
1098 	throw (cssxs::SAXException, cssu::RuntimeException)
1099 {
1100 	processingInstruction( aTarget, aData );
1101 }
1102 
1103 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_setDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const rtl::OUString& /*publicId*/, const rtl::OUString& /*systemId*/ )
1104 	throw (cssxs::SAXException, cssu::RuntimeException)
1105 {
1106 }
1107 
1108 rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName ()
1109 	throw (cssu::RuntimeException)
1110 {
1111 	return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1112 }
1113 
1114 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl_supportsService( const rtl::OUString& ServiceName )
1115 	throw (cssu::RuntimeException)
1116 {
1117 	return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1118 }
1119 
1120 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames(  )
1121 	throw (cssu::RuntimeException)
1122 {
1123 	cssu::Sequence < rtl::OUString > aRet(1);
1124 	rtl::OUString* pArray = aRet.getArray();
1125 	pArray[0] =  rtl::OUString ( RTL_ASCII_USTRINGPARAM ( SERVICE_NAME ) );
1126 	return aRet;
1127 }
1128 #undef SERVICE_NAME
1129 
1130 cssu::Reference< cssu::XInterface > SAL_CALL XMLDocumentWrapper_XmlSecImpl_createInstance(
1131 	const cssu::Reference< cssl::XMultiServiceFactory > &)
1132 	throw( cssu::Exception )
1133 {
1134 	return (cppu::OWeakObject*) new XMLDocumentWrapper_XmlSecImpl( );
1135 }
1136 
1137 /* XServiceInfo */
1138 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName(  )
1139 	throw (cssu::RuntimeException)
1140 {
1141 	return XMLDocumentWrapper_XmlSecImpl_getImplementationName();
1142 }
1143 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName )
1144 	throw (cssu::RuntimeException)
1145 {
1146 	return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName );
1147 }
1148 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames(  )
1149 	throw (cssu::RuntimeException)
1150 {
1151 	return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames();
1152 }
1153 
1154