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