xref: /AOO41X/main/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx (revision 06b3ce531745799678cf4bb887ef37436d81238b)
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 -- Retrives 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 retrived
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 -- Retrives 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