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