xref: /trunk/main/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 /****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************
201  *
202  *   NAME
203  *  sendStartElement -- Constructs a startElement SAX event
204  *
205  *   SYNOPSIS
206  *  sendStartElement(xHandler, xHandler2, pNode);
207  *
208  *   FUNCTION
209  *  Used when converting the document into SAX event stream.
210  *  This method constructs a startElement SAX event for a particular
211  *  element, then calls the startElement methods of the XDocumentHandlers.
212  *
213  *   INPUTS
214  *  xHandler -  the first XDocumentHandler interface to receive the
215  *          startElement SAX event. It can be NULL.
216  *  xHandler2 - the second XDocumentHandler interface to receive the
217  *          startElement SAX event. It can't be NULL.
218  *  pNode -     the node on which the startElement should be generated.
219  *          This node must be a element type.
220  *
221  *   RESULT
222  *  empty
223  *
224  *   HISTORY
225  *  05.01.2004 -    implemented
226  *
227  *   AUTHOR
228  *  Michael Mi
229  *  Email: michael.mi@sun.com
230  ******************************************************************************/
231 {
232     SvXMLAttributeList* pAttributeList = new SvXMLAttributeList();
233     cssu::Reference < cssxs::XAttributeList > xAttrList = cssu::Reference< cssxs::XAttributeList > (pAttributeList);
234 
235     xmlNsPtr pNsDef = pNode->nsDef;
236 
237     while (pNsDef != NULL)
238     {
239         const xmlChar* pNsPrefix = pNsDef->prefix;
240         const xmlChar* pNsHref = pNsDef->href;
241 
242         if (pNsDef->prefix == NULL)
243         {
244             pAttributeList->AddAttribute(
245                 rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )),
246                 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref )));
247         }
248         else
249         {
250             pAttributeList->AddAttribute(
251                 rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS ))
252                 +rtl::OUString(RTL_UTF8_USTRINGPARAM( ":" ))
253                 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsPrefix )),
254                 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref )));
255         }
256 
257         pNsDef = pNsDef->next;
258     }
259 
260     xmlAttrPtr pAttr = pNode->properties;
261 
262     while (pAttr != NULL)
263     {
264         const xmlChar* pAttrName = pAttr->name;
265         xmlNsPtr pAttrNs = pAttr->ns;
266 
267         rtl::OUString ouAttrName;
268         if (pAttrNs == NULL)
269         {
270             ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName ));
271         }
272         else
273         {
274             ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrNs->prefix))
275                 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)":" ))
276                 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName ));
277         }
278 
279         pAttributeList->AddAttribute(
280             ouAttrName,
281             rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)(pAttr->children->content))));
282         pAttr = pAttr->next;
283     }
284 
285     rtl::OString sNodeName = getNodeQName(pNode);
286 
287     if (xHandler.is())
288     {
289         xHandler->startElement(
290             rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )),
291             xAttrList);
292     }
293 
294     xHandler2->startElement(
295         rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )),
296         xAttrList);
297 }
298 
sendEndElement(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const299 void XMLDocumentWrapper_XmlSecImpl::sendEndElement(
300     const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
301     const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
302     const xmlNodePtr pNode) const
303 /****** XMLDocumentWrapper_XmlSecImpl/sendEndElement **************************
304  *
305  *   NAME
306  *  sendEndElement -- Constructs a endElement SAX event
307  *
308  *   SYNOPSIS
309  *  sendEndElement(xHandler, xHandler2, pNode);
310  *
311  *   FUNCTION
312  *  Used when converting the document into SAX event stream.
313  *  This method constructs a endElement SAX event for a particular
314  *  element, then calls the endElement methods of the XDocumentHandlers.
315  *
316  *   INPUTS
317  *  xHandler -  the first XDocumentHandler interface to receive the
318  *          endElement SAX event. It can be NULL.
319  *  xHandler2 - the second XDocumentHandler interface to receive the
320  *          endElement SAX event. It can't be NULL.
321  *  pNode -     the node on which the endElement should be generated.
322  *          This node must be a element type.
323  *
324  *   RESULT
325  *  empty
326  *
327  *   HISTORY
328  *  05.01.2004 -    implemented
329  *
330  *   AUTHOR
331  *  Michael Mi
332  *  Email: michael.mi@sun.com
333  ******************************************************************************/
334 {
335     rtl::OString sNodeName = getNodeQName(pNode);
336 
337     if (xHandler.is())
338     {
339         xHandler->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )));
340     }
341 
342     xHandler2->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )));
343 }
344 
sendNode(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const345 void XMLDocumentWrapper_XmlSecImpl::sendNode(
346     const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
347     const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
348     const xmlNodePtr pNode) const
349 /****** XMLDocumentWrapper_XmlSecImpl/sendNode ********************************
350  *
351  *   NAME
352  *  sendNode -- Constructs a characters SAX event or a
353  *  processingInstruction SAX event
354  *
355  *   SYNOPSIS
356  *  sendNode(xHandler, xHandler2, pNode);
357  *
358  *   FUNCTION
359  *  Used when converting the document into SAX event stream.
360  *  This method constructs a characters SAX event or a
361  *  processingInstructionfor SAX event based on the type of a particular
362  *  element, then calls the corresponding methods of the XDocumentHandlers.
363  *
364  *   INPUTS
365  *  xHandler -  the first XDocumentHandler interface to receive the
366  *          SAX event. It can be NULL.
367  *  xHandler2 - the second XDocumentHandler interface to receive the
368  *          SAX event. It can't be NULL.
369  *  pNode -     the node on which the endElement should be generated.
370  *          If it is a text node, then a characters SAX event is
371  *          generated; if it is a PI node, then a
372  *          processingInstructionfor SAX event is generated.
373  *
374  *   RESULT
375  *  empty
376  *
377  *   HISTORY
378  *  05.01.2004 -    implemented
379  *
380  *   AUTHOR
381  *  Michael Mi
382  *  Email: michael.mi@sun.com
383  ******************************************************************************/
384 {
385     xmlElementType type = pNode->type;
386 
387     if (type == XML_TEXT_NODE)
388     {
389         if (xHandler.is())
390         {
391             xHandler->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
392         }
393 
394         xHandler2->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
395     }
396     else if (type == XML_PI_NODE)
397     {
398         if (xHandler.is())
399         {
400             xHandler->processingInstruction(
401                 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )),
402                 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
403         }
404 
405         xHandler2->processingInstruction(
406             rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )),
407             rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) )));
408     }
409 }
410 
getNodeQName(const xmlNodePtr pNode) const411 rtl::OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode) const
412 /****** XMLDocumentWrapper_XmlSecImpl/getNodeQName ****************************
413  *
414  *   NAME
415  *  getNodeQName -- Retrieves the qualified name of a node
416  *
417  *   SYNOPSIS
418  *  name = getNodeQName(pNode);
419  *
420  *   FUNCTION
421  *  see NAME
422  *
423  *   INPUTS
424  *  pNode - the node whose name will be retrieved
425  *
426  *   RESULT
427  *  name - the node's qualified name
428  *
429  *   HISTORY
430  *  05.01.2004 -    implemented
431  *
432  *   AUTHOR
433  *  Michael Mi
434  *  Email: michael.mi@sun.com
435  ******************************************************************************/
436 {
437     rtl::OString sNodeName((const sal_Char*)pNode->name);
438     if (pNode->ns != NULL)
439     {
440         xmlNsPtr pNs = pNode->ns;
441 
442         if (pNs->prefix != NULL)
443         {
444             rtl::OString sPrefix((const sal_Char*)pNs->prefix);
445             sNodeName = sPrefix+rtl::OString(":")+sNodeName;
446         }
447     }
448 
449     return sNodeName;
450 }
451 
checkElement(const cssu::Reference<cssxw::XXMLElementWrapper> & xXMLElement) const452 xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const cssu::Reference< cssxw::XXMLElementWrapper >& xXMLElement) const
453 /****** XMLDocumentWrapper_XmlSecImpl/checkElement ****************************
454  *
455  *   NAME
456  *  checkElement -- Retrieves the node wrapped by an XXMLElementWrapper
457  *  interface
458  *
459  *   SYNOPSIS
460  *  node = checkElement(xXMLElement);
461  *
462  *   FUNCTION
463  *  see NAME
464  *
465  *   INPUTS
466  *  xXMLElement -   the XXMLElementWrapper interface wrapping a node
467  *
468  *   RESULT
469  *  node - the node wrapped in the XXMLElementWrapper interface
470  *
471  *   HISTORY
472  *  05.01.2004 -    implemented
473  *
474  *   AUTHOR
475  *  Michael Mi
476  *  Email: michael.mi@sun.com
477  ******************************************************************************/
478 {
479     xmlNodePtr rc = NULL;
480 
481     if (xXMLElement.is())
482     {
483         cssu::Reference< cssl::XUnoTunnel > xNodTunnel( xXMLElement, cssu::UNO_QUERY ) ;
484         if( !xNodTunnel.is() )
485         {
486             throw cssu::RuntimeException() ;
487         }
488 
489         XMLElementWrapper_XmlSecImpl* pElement
490             = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
491                 sal::static_int_cast<sal_uIntPtr>(
492                     xNodTunnel->getSomething(
493                         XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ))) ;
494 
495         if( pElement == NULL ) {
496             throw cssu::RuntimeException() ;
497         }
498 
499         rc = pElement->getNativeElement();
500     }
501 
502     return rc;
503 }
504 
recursiveDelete(const xmlNodePtr pNode)505 sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete(
506     const xmlNodePtr pNode)
507 /****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete *************************
508  *
509  *   NAME
510  *  recursiveDelete -- Deletes a particular node with its branch.
511  *
512  *   SYNOPSIS
513  *  result = recursiveDelete(pNode);
514  *
515  *   FUNCTION
516  *  Deletes a particular node with its branch, while reserving the nodes
517  *  (and their brance) listed in the m_aReservedNodes.
518  *  The deletion process is preformed in the tree order, that is, a node
519  *  is deleted after its previous sibling node is deleted, a parent node
520  *  is deleted after its branch is deleted.
521  *  During the deletion process when the m_pStopAtNode is reached, the
522  *  progress is interrupted at once.
523  *
524  *   INPUTS
525  *  pNode - the node to be deleted
526  *
527  *   RESULT
528  *  result -    the result of the deletion process, can be one of following
529  *          values:
530  *          NODE_STOPED - the process is interrupted by meeting the
531  *              m_pStopAtNode
532  *          NODE_NOTREMOVED - the pNode is not completely removed
533  *              because there is its descendant in the
534  *              m_aReservedNodes list
535  *          NODE_REMOVED - the pNode and its branch are completely
536  *              removed
537  *
538  *   NOTES
539  *  The node in the m_aReservedNodes list must be in the tree order, otherwise
540  *  the result is unpredictable.
541  *
542  *   HISTORY
543  *  05.01.2004 -    implemented
544  *
545  *   AUTHOR
546  *  Michael Mi
547  *  Email: michael.mi@sun.com
548  ******************************************************************************/
549 {
550     if (pNode == m_pStopAtNode)
551     {
552         return NODE_STOPED;
553     }
554 
555     if (pNode != m_pCurrentReservedNode)
556     {
557         xmlNodePtr pChild = pNode->children;
558 
559         xmlNodePtr pNextSibling;
560         bool bIsRemoved = true;
561         sal_Int32 nResult;
562 
563         while( pChild != NULL )
564         {
565             pNextSibling = pChild->next;
566             nResult = recursiveDelete(pChild);
567 
568             switch (nResult)
569             {
570             case NODE_STOPED:
571                 return NODE_STOPED;
572             case NODE_NOTREMOVED:
573                 bIsRemoved = false;
574                 break;
575             case NODE_REMOVED:
576                 removeNode(pChild);
577                 break;
578             default:
579                 throw cssu::RuntimeException();
580             }
581 
582             pChild = pNextSibling;
583         }
584 
585         if (pNode == m_pCurrentElement)
586         {
587             bIsRemoved = false;
588         }
589 
590         return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED;
591     }
592     else
593     {
594         getNextReservedNode();
595         return NODE_NOTREMOVED;
596     }
597 }
598 
getNextReservedNode()599 void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode()
600 /****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode *********************
601  *
602  *   NAME
603  *  getNextReservedNode -- Highlights the next reserved node in the
604  *  reserved node list
605  *
606  *   SYNOPSIS
607  *  getNextReservedNode();
608  *
609  *   FUNCTION
610  *  The m_aReservedNodes array holds a node list, while the
611  *  m_pCurrentReservedNode points to the one currently highlighted.
612  *  This method is used to highlight the next node in the node list.
613  *  This method is called at the time when the current highlighted node
614  *  has been already processed, and the next node should be ready.
615  *
616  *   INPUTS
617  *  empty
618  *
619  *   RESULT
620  *  empty
621  *
622  *   HISTORY
623  *  05.01.2004 -    implemented
624  *
625  *   AUTHOR
626  *  Michael Mi
627  *  Email: michael.mi@sun.com
628  ******************************************************************************/
629 {
630     if (m_nReservedNodeIndex < m_aReservedNodes.getLength())
631     {
632         m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] );
633         m_nReservedNodeIndex ++;
634     }
635     else
636     {
637         m_pCurrentReservedNode = NULL;
638     }
639 }
640 
removeNode(const xmlNodePtr pNode) const641 void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const
642 /****** XMLDocumentWrapper_XmlSecImpl/removeNode ******************************
643  *
644  *   NAME
645  *  removeNode -- Deletes a node with its branch unconditionaly
646  *
647  *   SYNOPSIS
648  *  removeNode( pNode );
649  *
650  *   FUNCTION
651  *  Delete the node along with its branch from the document.
652  *
653  *   INPUTS
654  *  pNode - the node to be deleted
655  *
656  *   RESULT
657  *  empty
658  *
659  *   HISTORY
660  *  05.01.2004 -    implemented
661  *
662  *   AUTHOR
663  *  Michael Mi
664  *  Email: michael.mi@sun.com
665  ******************************************************************************/
666 {
667     /* you can't remove the current node */
668     OSL_ASSERT( m_pCurrentElement != pNode );
669 
670     xmlAttrPtr pAttr = pNode->properties;
671 
672     while (pAttr != NULL)
673     {
674         if (!stricmp((sal_Char*)pAttr->name,"id"))
675         {
676             xmlRemoveID(m_pDocument, pAttr);
677         }
678 
679         pAttr = pAttr->next;
680     }
681 
682     xmlUnlinkNode(pNode);
683     xmlFreeNode(pNode);
684 }
685 
buildIDAttr(xmlNodePtr pNode) const686 void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const
687 /****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr *****************************
688  *
689  *   NAME
690  *  buildIDAttr -- build the ID attribute of a node
691  *
692  *   SYNOPSIS
693  *  buildIDAttr( pNode );
694  *
695  *   FUNCTION
696  *  see NAME
697  *
698  *   INPUTS
699  *  pNode - the node whose id attribute will be built
700  *
701  *   RESULT
702  *  empty
703  *
704  *   HISTORY
705  *  14.06.2004 -    implemented
706  *
707  *   AUTHOR
708  *  Michael Mi
709  *  Email: michael.mi@sun.com
710  ******************************************************************************/
711 {
712     xmlAttrPtr idAttr = xmlHasProp( pNode, (const unsigned char *)"id" );
713     if (idAttr == NULL)
714     {
715         idAttr = xmlHasProp( pNode, (const unsigned char *)"Id" );
716     }
717 
718     if (idAttr != NULL)
719     {
720         xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ;
721         xmlAddID( NULL, m_pDocument, idValue, idAttr );
722     }
723 }
724 
rebuildIDLink(xmlNodePtr pNode) const725 void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const
726 /****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink ***************************
727  *
728  *   NAME
729  *  rebuildIDLink -- rebuild the ID link for the branch
730  *
731  *   SYNOPSIS
732  *  rebuildIDLink( pNode );
733  *
734  *   FUNCTION
735  *  see NAME
736  *
737  *   INPUTS
738  *  pNode - the node, from which the branch will be rebuilt
739  *
740  *   RESULT
741  *  empty
742  *
743  *   HISTORY
744  *  14.06.2004 -    implemented
745  *
746  *   AUTHOR
747  *  Michael Mi
748  *  Email: michael.mi@sun.com
749  ******************************************************************************/
750 {
751     if (pNode != NULL && pNode->type == XML_ELEMENT_NODE)
752     {
753         buildIDAttr( pNode );
754 
755         xmlNodePtr child = pNode->children;
756         while (child != NULL)
757         {
758             rebuildIDLink(child);
759             child = child->next;
760         }
761     }
762 }
763 
764 /* XXMLDocumentWrapper */
getCurrentElement()765 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement(  )
766 {
767     XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement);
768     return (cssu::Reference< cssxw::XXMLElementWrapper >)pElement;
769 }
770 
setCurrentElement(const cssu::Reference<cssxw::XXMLElementWrapper> & element)771 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const cssu::Reference< cssxw::XXMLElementWrapper >& element )
772 {
773     m_pCurrentElement = checkElement( element );
774     saxHelper.setCurrentNode( m_pCurrentElement );
775 }
776 
removeCurrentElement()777 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement(  )
778 {
779     OSL_ASSERT( m_pCurrentElement != NULL );
780 
781     xmlNodePtr pOldCurrentElement = m_pCurrentElement;
782 
783     /*
784      * pop the top node in the parser context's
785      * nodeTab stack, then the parent of that node will
786      * automatically become the new stack top, and
787      * the current node as well.
788      */
789     saxHelper.endElement(
790         rtl::OUString(
791             RTL_UTF8_USTRINGPARAM (
792                 (sal_Char*)(pOldCurrentElement->name)
793             )));
794     m_pCurrentElement = saxHelper.getCurrentNode();
795 
796     /*
797      * remove the node
798      */
799     removeNode(pOldCurrentElement);
800 }
801 
isCurrent(const cssu::Reference<cssxw::XXMLElementWrapper> & node)802 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
803 {
804     xmlNodePtr pNode = checkElement(node);
805     return (pNode == m_pCurrentElement);
806 }
807 
isCurrentElementEmpty()808 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty(  )
809 {
810     sal_Bool rc = sal_False;
811 
812     if (m_pCurrentElement->children == NULL)
813     {
814         rc = sal_True;
815     }
816 
817     return rc;
818 }
819 
getNodeName(const cssu::Reference<cssxw::XXMLElementWrapper> & node)820 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
821 {
822     xmlNodePtr pNode = checkElement(node);
823     return rtl::OUString(RTL_UTF8_USTRINGPARAM ( (sal_Char*)pNode->name ));
824 }
825 
clearUselessData(const cssu::Reference<cssxw::XXMLElementWrapper> & node,const cssu::Sequence<cssu::Reference<cssxw::XXMLElementWrapper>> & reservedDescendants,const cssu::Reference<cssxw::XXMLElementWrapper> & stopAtNode)826 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData(
827     const cssu::Reference< cssxw::XXMLElementWrapper >& node,
828     const cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >& reservedDescendants,
829     const cssu::Reference< cssxw::XXMLElementWrapper >& stopAtNode )
830 {
831     xmlNodePtr pTargetNode = checkElement(node);
832 
833     m_pStopAtNode = checkElement(stopAtNode);
834     m_aReservedNodes = reservedDescendants;
835     m_nReservedNodeIndex = 0;
836 
837     getNextReservedNode();
838 
839     recursiveDelete(pTargetNode);
840 }
841 
collapse(const cssu::Reference<cssxw::XXMLElementWrapper> & node)842 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
843 {
844     xmlNodePtr pTargetNode = checkElement(node);
845     xmlNodePtr pParent;
846 
847     while (pTargetNode != NULL)
848     {
849         if (pTargetNode->children != NULL || pTargetNode == m_pCurrentElement)
850         {
851             break;
852         }
853 
854         pParent = pTargetNode->parent;
855         removeNode(pTargetNode);
856         pTargetNode = pParent;
857     }
858 }
859 
getTree(const cssu::Reference<cssxs::XDocumentHandler> & handler)860 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const cssu::Reference< cssxs::XDocumentHandler >& handler )
861 {
862     if (m_pRootElement != NULL)
863     {
864         xmlNodePtr pTempCurrentElement = m_pCurrentElement;
865         sal_Int32 nTempCurrentPosition = m_nCurrentPosition;
866 
867         m_pCurrentElement = m_pRootElement;
868 
869         m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
870         cssu::Reference< cssxs::XDocumentHandler > xHandler = handler;
871 
872         while(true)
873         {
874             switch (m_nCurrentPosition)
875             {
876             case NODEPOSITION_STARTELEMENT:
877                 sendStartElement(NULL, xHandler, m_pCurrentElement);
878                 break;
879             case NODEPOSITION_ENDELEMENT:
880                 sendEndElement(NULL, xHandler, m_pCurrentElement);
881                 break;
882             case NODEPOSITION_NORMAL:
883                 sendNode(NULL, xHandler, m_pCurrentElement);
884                 break;
885             }
886 
887             if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT ))
888             {
889                 break;
890             }
891 
892             getNextSAXEvent();
893         }
894 
895         m_pCurrentElement = pTempCurrentElement;
896         m_nCurrentPosition = nTempCurrentPosition;
897     }
898 }
899 
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)900 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents(
901     const cssu::Reference< cssxs::XDocumentHandler >& handler,
902     const cssu::Reference< cssxs::XDocumentHandler >& xEventKeeperHandler,
903     const cssu::Reference< cssxw::XXMLElementWrapper >& startNode,
904     const cssu::Reference< cssxw::XXMLElementWrapper >& endNode )
905 {
906         /*
907          * The first SAX event is the startElement of the startNode
908          * element.
909          */
910     bool bHasCurrentElementChild = (m_pCurrentElement->children != NULL);
911 
912     xmlNodePtr pTempCurrentElement = m_pCurrentElement;
913 
914     m_pCurrentElement = checkElement(startNode);
915 
916     if (m_pCurrentElement->type == XML_ELEMENT_NODE)
917     {
918         m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
919     }
920     else
921     {
922         m_nCurrentPosition = NODEPOSITION_NORMAL;
923     }
924 
925     xmlNodePtr pEndNode = checkElement(endNode);
926 
927     cssu::Reference < cssxc::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, cssu::UNO_QUERY );
928 
929     cssu::Reference< cssxs::XDocumentHandler > xHandler = handler;
930 
931     while(true)
932     {
933         switch (m_nCurrentPosition)
934         {
935         case NODEPOSITION_STARTELEMENT:
936             sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
937             break;
938         case NODEPOSITION_ENDELEMENT:
939             sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
940             break;
941         case NODEPOSITION_NORMAL:
942             sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement);
943             break;
944         default:
945             throw cssu::RuntimeException();
946         }
947 
948         if (xSAXEventKeeper->isBlocking())
949         {
950             xHandler = NULL;
951         }
952 
953         if (pEndNode == NULL &&
954             ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) ||
955              (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT)))
956         {
957             break;
958         }
959 
960         getNextSAXEvent();
961 
962             /*
963              * If there is an end point specified, then check whether
964              * the current node equals to the end point. If so, stop
965              * generating.
966              */
967         if (pEndNode != NULL && m_pCurrentElement == pEndNode)
968         {
969             break;
970         }
971     }
972 
973     m_pCurrentElement = pTempCurrentElement;
974 }
975 
rebuildIDLink(const com::sun::star::uno::Reference<com::sun::star::xml::wrapper::XXMLElementWrapper> & node)976 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(
977     const com::sun::star::uno::Reference< com::sun::star::xml::wrapper::XXMLElementWrapper >& node )
978 {
979     xmlNodePtr pNode = checkElement( node );
980     rebuildIDLink(pNode);
981 }
982 
983 
984 /* cssxs::XDocumentHandler */
startDocument()985 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument(  )
986 {
987 }
988 
endDocument()989 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument(  )
990 {
991 }
992 
startElement(const rtl::OUString & aName,const cssu::Reference<cssxs::XAttributeList> & xAttribs)993 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const rtl::OUString& aName, const cssu::Reference< cssxs::XAttributeList >& xAttribs )
994 {
995     sal_Int32 nLength = xAttribs->getLength();
996     cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
997 
998     for (int i = 0; i < nLength; ++i)
999     {
1000         aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1001         aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1002     }
1003 
1004     _startElement(aName, aAttributes);
1005 }
1006 
endElement(const rtl::OUString & aName)1007 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const rtl::OUString& aName )
1008 {
1009     saxHelper.endElement(aName);
1010     m_pCurrentElement = saxHelper.getCurrentNode();
1011 }
1012 
characters(const rtl::OUString & aChars)1013 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars )
1014 {
1015     saxHelper.characters(aChars);
1016 }
1017 
ignorableWhitespace(const rtl::OUString & aWhitespaces)1018 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1019 {
1020     saxHelper.ignorableWhitespace(aWhitespaces);
1021 }
1022 
processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)1023 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
1024 {
1025     saxHelper.processingInstruction(aTarget, aData);
1026 }
1027 
setDocumentLocator(const cssu::Reference<cssxs::XLocator> & xLocator)1028 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator )
1029 {
1030     saxHelper.setDocumentLocator(xLocator);
1031 }
1032 
1033 /* XCompressedDocumentHandler */
_startDocument()1034 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument(  )
1035 {
1036 }
1037 
_endDocument()1038 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument(  )
1039 {
1040 }
1041 
_startElement(const rtl::OUString & aName,const cssu::Sequence<cssxcsax::XMLAttribute> & aAttributes)1042 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startElement( const rtl::OUString& aName, const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
1043 {
1044     saxHelper.startElement(aName, aAttributes);
1045     m_pCurrentElement = saxHelper.getCurrentNode();
1046 
1047     buildIDAttr( m_pCurrentElement );
1048 }
1049 
_endElement(const rtl::OUString & aName)1050 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName )
1051 {
1052     endElement( aName );
1053 }
1054 
_characters(const rtl::OUString & aChars)1055 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars )
1056 {
1057     characters( aChars );
1058 }
1059 
_ignorableWhitespace(const rtl::OUString & aWhitespaces)1060 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces )
1061 {
1062     ignorableWhitespace( aWhitespaces );
1063 }
1064 
_processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)1065 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
1066 {
1067     processingInstruction( aTarget, aData );
1068 }
1069 
_setDocumentLocator(sal_Int32,sal_Int32,const rtl::OUString &,const rtl::OUString &)1070 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_setDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const rtl::OUString& /*publicId*/, const rtl::OUString& /*systemId*/ )
1071 {
1072 }
1073 
XMLDocumentWrapper_XmlSecImpl_getImplementationName()1074 rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName ()
1075 {
1076     return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1077 }
1078 
XMLDocumentWrapper_XmlSecImpl_supportsService(const rtl::OUString & ServiceName)1079 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl_supportsService( const rtl::OUString& ServiceName )
1080 {
1081     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1082 }
1083 
XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames()1084 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames(  )
1085 {
1086     cssu::Sequence < rtl::OUString > aRet(1);
1087     rtl::OUString* pArray = aRet.getArray();
1088     pArray[0] =  rtl::OUString ( RTL_ASCII_USTRINGPARAM ( SERVICE_NAME ) );
1089     return aRet;
1090 }
1091 #undef SERVICE_NAME
1092 
XMLDocumentWrapper_XmlSecImpl_createInstance(const cssu::Reference<cssl::XMultiServiceFactory> &)1093 cssu::Reference< cssu::XInterface > SAL_CALL XMLDocumentWrapper_XmlSecImpl_createInstance(
1094     const cssu::Reference< cssl::XMultiServiceFactory > &)
1095 {
1096     return (cppu::OWeakObject*) new XMLDocumentWrapper_XmlSecImpl( );
1097 }
1098 
1099 /* XServiceInfo */
getImplementationName()1100 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName(  )
1101 {
1102     return XMLDocumentWrapper_XmlSecImpl_getImplementationName();
1103 }
supportsService(const rtl::OUString & rServiceName)1104 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName )
1105 {
1106     return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName );
1107 }
getSupportedServiceNames()1108 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames(  )
1109 {
1110     return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames();
1111 }
1112