Bump version to 6.0-36
[LibreOffice.git] / xmlsecurity / source / xmlsec / xmldocumentwrapper_xmlsecimpl.cxx
blob75da47627c18d71fda61d428fb1fab6a2598799f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <osl/diagnose.h>
23 #include <com/sun/star/uno/XComponentContext.hpp>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
26 #include <xmlsec/xmlelementwrapper_xmlsecimpl.hxx>
28 #include <xmloff/attrlist.hxx>
30 #include <stdlib.h>
31 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
36 #include <vector>
38 #ifdef UNX
39 #define stricmp strcasecmp
40 #endif
42 namespace cssu = com::sun::star::uno;
43 namespace cssl = com::sun::star::lang;
44 namespace cssxc = com::sun::star::xml::crypto;
45 namespace cssxcsax = com::sun::star::xml::csax;
46 namespace cssxs = com::sun::star::xml::sax;
47 namespace cssxw = com::sun::star::xml::wrapper;
49 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.XMLDocumentWrapper_XmlSecImpl"
51 #define STRXMLNS "xmlns"
53 /* used by the recursiveDelete method */
54 #define NODE_REMOVED 0
55 #define NODE_NOTREMOVED 1
56 #define NODE_STOPED 2
58 XMLDocumentWrapper_XmlSecImpl::XMLDocumentWrapper_XmlSecImpl()
59 : m_nCurrentPosition(0)
60 , m_pStopAtNode(nullptr)
61 , m_pCurrentReservedNode(nullptr)
62 , m_nReservedNodeIndex(0)
64 saxHelper.startDocument();
65 m_pDocument = saxHelper.getDocument();
68 * creates the virtual root element
70 saxHelper.startElement("root", cssu::Sequence<cssxcsax::XMLAttribute>());
72 m_pRootElement = saxHelper.getCurrentNode();
73 m_pCurrentElement = m_pRootElement;
76 XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl()
78 saxHelper.endDocument();
79 xmlFreeDoc(m_pDocument);
82 void XMLDocumentWrapper_XmlSecImpl::getNextSAXEvent()
83 /****** XMLDocumentWrapper_XmlSecImpl/getNextSAXEvent *************************
85 * NAME
86 * getNextSAXEvent -- Prepares the next SAX event to be manipulate
88 * FUNCTION
89 * When converting the document into SAX events, this method is used to
90 * decide the next SAX event to be generated.
91 * Two member variables are checked to make the decision, the
92 * m_pCurrentElement and the m_nCurrentPosition.
93 * The m_pCurrentElement represents the node which have been covered, and
94 * the m_nCurrentPosition represents the event which have been sent.
95 * For example, suppose that the m_pCurrentElement
96 * points to element A, and the m_nCurrentPosition equals to
97 * NODEPOSITION_STARTELEMENT, then the next SAX event should be the
98 * endElement for element A if A has no child, or startElement for the
99 * first child element of element A otherwise.
100 * The m_nCurrentPosition can be one of following values:
101 * NODEPOSITION_STARTELEMENT for startElement;
102 * NODEPOSITION_ENDELEMENT for endElement;
103 * NODEPOSITION_NORMAL for other SAX events;
104 ******************************************************************************/
106 OSL_ASSERT( m_pCurrentElement != nullptr );
109 * Get the next event through tree order.
111 * if the current event is a startElement, then the next
112 * event depends on whether or not the current node has
113 * children.
115 if (m_nCurrentPosition == NODEPOSITION_STARTELEMENT)
118 * If the current node has children, then its first child
119 * should be next current node, and the next event will be
120 * startElement or characters(PI) based on that child's node
121 * type. Otherwise, the endElement of current node is the
122 * next event.
124 if (m_pCurrentElement->children != nullptr)
126 m_pCurrentElement = m_pCurrentElement->children;
127 m_nCurrentPosition
128 = (m_pCurrentElement->type == XML_ELEMENT_NODE)?
129 NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL;
131 else
133 m_nCurrentPosition = NODEPOSITION_ENDELEMENT;
137 * if the current event is a not startElement, then the next
138 * event depends on whether or not the current node has
139 * following sibling.
141 else if (m_nCurrentPosition == NODEPOSITION_ENDELEMENT || m_nCurrentPosition == NODEPOSITION_NORMAL)
143 xmlNodePtr pNextSibling = m_pCurrentElement->next;
146 * If the current node has following sibling, that sibling
147 * should be next current node, and the next event will be
148 * startElement or characters(PI) based on that sibling's node
149 * type. Otherwise, the endElement of current node's parent
150 * becomes the next event.
152 if (pNextSibling != nullptr)
154 m_pCurrentElement = pNextSibling;
155 m_nCurrentPosition
156 = (m_pCurrentElement->type == XML_ELEMENT_NODE)?
157 NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL;
159 else
161 m_pCurrentElement = m_pCurrentElement->parent;
162 m_nCurrentPosition = NODEPOSITION_ENDELEMENT;
167 void XMLDocumentWrapper_XmlSecImpl::sendStartElement(
168 const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
169 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
170 const xmlNodePtr pNode)
171 /****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************
173 * NAME
174 * sendStartElement -- Constructs a startElement SAX event
176 * FUNCTION
177 * Used when converting the document into SAX event stream.
178 * This method constructs a startElement SAX event for a particular
179 * element, then calls the startElement methods of the XDocumentHandlers.
181 * INPUTS
182 * xHandler - the first XDocumentHandler interface to receive the
183 * startElement SAX event. It can be NULL.
184 * xHandler2 - the second XDocumentHandler interface to receive the
185 * startElement SAX event. It can't be NULL.
186 * pNode - the node on which the startElement should be generated.
187 * This node must be a element type.
188 ******************************************************************************/
190 SvXMLAttributeList* pAttributeList = new SvXMLAttributeList();
191 cssu::Reference < cssxs::XAttributeList > xAttrList(pAttributeList);
193 xmlNsPtr pNsDef = pNode->nsDef;
195 while (pNsDef != nullptr)
197 const xmlChar* pNsPrefix = pNsDef->prefix;
198 const xmlChar* pNsHref = pNsDef->href;
200 if (pNsDef->prefix == nullptr)
202 pAttributeList->AddAttribute(
203 STRXMLNS,
204 OUString::fromUtf8(reinterpret_cast<char const *>(pNsHref)));
206 else
208 pAttributeList->AddAttribute(
209 STRXMLNS ":"
210 +OUString::fromUtf8(reinterpret_cast<char const *>(pNsPrefix)),
211 OUString::fromUtf8(reinterpret_cast<char const *>(pNsHref)));
214 pNsDef = pNsDef->next;
217 xmlAttrPtr pAttr = pNode->properties;
219 while (pAttr != nullptr)
221 const xmlChar* pAttrName = pAttr->name;
222 xmlNsPtr pAttrNs = pAttr->ns;
224 OUString ouAttrName;
225 if (pAttrNs == nullptr)
227 ouAttrName = OUString::fromUtf8(reinterpret_cast<char const *>(pAttrName));
229 else
231 ouAttrName = OUString::fromUtf8(reinterpret_cast<char const *>(pAttrNs->prefix))
232 + ":" + OUString::fromUtf8(reinterpret_cast<char const *>(pAttrName));
235 pAttributeList->AddAttribute(
236 ouAttrName,
237 OUString::fromUtf8(reinterpret_cast<char*>(pAttr->children->content)));
238 pAttr = pAttr->next;
241 OString sNodeName = getNodeQName(pNode);
243 if (xHandler.is())
245 xHandler->startElement(
246 OUString::fromUtf8(sNodeName),
247 xAttrList);
250 xHandler2->startElement(
251 OUString::fromUtf8(sNodeName),
252 xAttrList);
255 void XMLDocumentWrapper_XmlSecImpl::sendEndElement(
256 const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
257 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
258 const xmlNodePtr pNode)
259 /****** XMLDocumentWrapper_XmlSecImpl/sendEndElement **************************
261 * NAME
262 * sendEndElement -- Constructs a endElement SAX event
264 * FUNCTION
265 * Used when converting the document into SAX event stream.
266 * This method constructs a endElement SAX event for a particular
267 * element, then calls the endElement methods of the XDocumentHandlers.
269 * INPUTS
270 * xHandler - the first XDocumentHandler interface to receive the
271 * endElement SAX event. It can be NULL.
272 * xHandler2 - the second XDocumentHandler interface to receive the
273 * endElement SAX event. It can't be NULL.
274 * pNode - the node on which the endElement should be generated.
275 * This node must be a element type.
276 ******************************************************************************/
278 OString sNodeName = getNodeQName(pNode);
280 if (xHandler.is())
282 xHandler->endElement(OUString::fromUtf8(sNodeName));
285 xHandler2->endElement(OUString::fromUtf8(sNodeName));
288 void XMLDocumentWrapper_XmlSecImpl::sendNode(
289 const cssu::Reference< cssxs::XDocumentHandler >& xHandler,
290 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2,
291 const xmlNodePtr pNode)
292 /****** XMLDocumentWrapper_XmlSecImpl/sendNode ********************************
294 * NAME
295 * sendNode -- Constructs a characters SAX event or a
296 * processingInstruction SAX event
298 * FUNCTION
299 * Used when converting the document into SAX event stream.
300 * This method constructs a characters SAX event or a
301 * processingInstructionfor SAX event based on the type of a particular
302 * element, then calls the corresponding methods of the XDocumentHandlers.
304 * INPUTS
305 * xHandler - the first XDocumentHandler interface to receive the
306 * SAX event. It can be NULL.
307 * xHandler2 - the second XDocumentHandler interface to receive the
308 * SAX event. It can't be NULL.
309 * pNode - the node on which the endElement should be generated.
310 * If it is a text node, then a characters SAX event is
311 * generated; if it is a PI node, then a
312 * processingInstructionfor SAX event is generated.
313 ******************************************************************************/
315 xmlElementType type = pNode->type;
317 if (type == XML_TEXT_NODE)
319 if (xHandler.is())
321 xHandler->characters(OUString::fromUtf8(reinterpret_cast<char*>(pNode->content)));
324 xHandler2->characters(OUString::fromUtf8(reinterpret_cast<char*>(pNode->content)));
326 else if (type == XML_PI_NODE)
328 if (xHandler.is())
330 xHandler->processingInstruction(
331 OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)),
332 OUString::fromUtf8(reinterpret_cast<char const *>(pNode->content)));
335 xHandler2->processingInstruction(
336 OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)),
337 OUString::fromUtf8(reinterpret_cast<char*>(pNode->content)));
341 OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode)
342 /****** XMLDocumentWrapper_XmlSecImpl/getNodeQName ****************************
344 * NAME
345 * getNodeQName -- Retrieves the qualified name of a node
347 * INPUTS
348 * pNode - the node whose name will be retrieved
350 * RESULT
351 * name - the node's qualified name
352 ******************************************************************************/
354 OString sNodeName(reinterpret_cast<const char*>(pNode->name));
355 if (pNode->ns != nullptr)
357 xmlNsPtr pNs = pNode->ns;
359 if (pNs->prefix != nullptr)
361 OString sPrefix(reinterpret_cast<const char*>(pNs->prefix));
362 sNodeName = sPrefix+OString(":")+sNodeName;
366 return sNodeName;
369 xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const cssu::Reference< cssxw::XXMLElementWrapper >& xXMLElement)
370 /****** XMLDocumentWrapper_XmlSecImpl/checkElement ****************************
372 * NAME
373 * checkElement -- Retrieves the node wrapped by an XXMLElementWrapper
374 * interface
376 * INPUTS
377 * xXMLElement - the XXMLElementWrapper interface wraping a node
379 * RESULT
380 * node - the node wrapped in the XXMLElementWrapper interface
381 ******************************************************************************/
383 xmlNodePtr rc = nullptr;
385 if (xXMLElement.is())
387 cssu::Reference< cssl::XUnoTunnel > xNodTunnel( xXMLElement, cssu::UNO_QUERY_THROW ) ;
388 XMLElementWrapper_XmlSecImpl* pElement
389 = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
390 sal::static_int_cast<sal_uIntPtr>(
391 xNodTunnel->getSomething(
392 XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ))) ;
394 if( pElement == nullptr ) {
395 throw cssu::RuntimeException() ;
398 rc = pElement->getNativeElement();
401 return rc;
404 sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete(
405 const xmlNodePtr pNode)
406 /****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete *************************
408 * NAME
409 * recursiveDelete -- Deletes a particular node with its branch.
411 * FUNCTION
412 * Deletes a particular node with its branch, while reserving the nodes
413 * (and their branches) listed in the m_aReservedNodes.
414 * The deletion process is performed in the tree order, that is, a node
415 * is deleted after its previous sibling node is deleted, a parent node
416 * is deleted after its branch is deleted.
417 * During the deletion process when the m_pStopAtNode is reached, the
418 * progress is interrupted at once.
420 * INPUTS
421 * pNode - the node to be deleted
423 * RESULT
424 * result - the result of the deletion process, can be one of following
425 * values:
426 * NODE_STOPED - the process is interrupted by meeting the
427 * m_pStopAtNode
428 * NODE_NOTREMOVED - the pNode is not completely removed
429 * because there is its descendant in the
430 * m_aReservedNodes list
431 * NODE_REMOVED - the pNode and its branch are completely
432 * removed
434 * NOTES
435 * The node in the m_aReservedNodes list must be in the tree order, otherwise
436 * the result is unpredictable.
437 ******************************************************************************/
439 if (pNode == m_pStopAtNode)
441 return NODE_STOPED;
444 if (pNode != m_pCurrentReservedNode)
446 xmlNodePtr pChild = pNode->children;
448 xmlNodePtr pNextSibling;
449 bool bIsRemoved = true;
450 sal_Int32 nResult;
452 while( pChild != nullptr )
454 pNextSibling = pChild->next;
455 nResult = recursiveDelete(pChild);
457 switch (nResult)
459 case NODE_STOPED:
460 return NODE_STOPED;
461 case NODE_NOTREMOVED:
462 bIsRemoved = false;
463 break;
464 case NODE_REMOVED:
465 removeNode(pChild);
466 break;
467 default:
468 throw cssu::RuntimeException();
471 pChild = pNextSibling;
474 if (pNode == m_pCurrentElement)
476 bIsRemoved = false;
479 return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED;
481 else
483 getNextReservedNode();
484 return NODE_NOTREMOVED;
488 void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode()
489 /****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode *********************
491 * NAME
492 * getNextReservedNode -- Highlights the next reserved node in the
493 * reserved node list
495 * FUNCTION
496 * The m_aReservedNodes array holds a node list, while the
497 * m_pCurrentReservedNode points to the one currently highlighted.
498 * This method is used to highlight the next node in the node list.
499 * This method is called at the time when the current highlighted node
500 * has been already processed, and the next node should be ready.
501 ******************************************************************************/
503 if (m_nReservedNodeIndex < m_aReservedNodes.getLength())
505 m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] );
506 m_nReservedNodeIndex ++;
508 else
510 m_pCurrentReservedNode = nullptr;
514 void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const
515 /****** XMLDocumentWrapper_XmlSecImpl/removeNode ******************************
517 * NAME
518 * removeNode -- Deletes a node with its branch unconditionally
520 * FUNCTION
521 * Delete the node along with its branch from the document.
523 * INPUTS
524 * pNode - the node to be deleted
525 ******************************************************************************/
527 /* you can't remove the current node */
528 OSL_ASSERT( m_pCurrentElement != pNode );
530 xmlAttrPtr pAttr = pNode->properties;
532 while (pAttr != nullptr)
534 if (!stricmp(reinterpret_cast<char const *>(pAttr->name), "id"))
536 xmlRemoveID(m_pDocument, pAttr);
539 pAttr = pAttr->next;
542 xmlUnlinkNode(pNode);
543 xmlFreeNode(pNode);
546 void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const
547 /****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr *****************************
549 * NAME
550 * buildIDAttr -- build the ID attribute of a node
552 * INPUTS
553 * pNode - the node whose id attribute will be built
554 ******************************************************************************/
556 xmlAttrPtr idAttr = xmlHasProp( pNode, reinterpret_cast<const unsigned char *>("id") );
557 if (idAttr == nullptr)
559 idAttr = xmlHasProp( pNode, reinterpret_cast<const unsigned char *>("Id") );
562 if (idAttr != nullptr)
564 xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ;
565 xmlAddID( nullptr, m_pDocument, idValue, idAttr );
569 void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const
570 /****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink ***************************
572 * NAME
573 * rebuildIDLink -- rebuild the ID link for the branch
575 * INPUTS
576 * pNode - the node, from which the branch will be rebuilt
577 ******************************************************************************/
579 if (pNode != nullptr && pNode->type == XML_ELEMENT_NODE)
581 buildIDAttr( pNode );
583 xmlNodePtr child = pNode->children;
584 while (child != nullptr)
586 rebuildIDLink(child);
587 child = child->next;
592 /* XXMLDocumentWrapper */
593 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement( )
595 XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement);
596 return cssu::Reference< cssxw::XXMLElementWrapper >(pElement);
599 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const cssu::Reference< cssxw::XXMLElementWrapper >& element )
601 m_pCurrentElement = checkElement( element );
602 saxHelper.setCurrentNode( m_pCurrentElement );
605 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement( )
607 OSL_ASSERT( m_pCurrentElement != nullptr );
609 xmlNodePtr pOldCurrentElement = m_pCurrentElement;
612 * pop the top node in the parser context's
613 * nodeTab stack, then the parent of that node will
614 * automatically become the new stack top, and
615 * the current node as well.
617 saxHelper.endElement(OUString::fromUtf8(reinterpret_cast<char const *>(pOldCurrentElement->name)));
618 m_pCurrentElement = saxHelper.getCurrentNode();
621 * remove the node
623 removeNode(pOldCurrentElement);
626 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
628 xmlNodePtr pNode = checkElement(node);
629 return (pNode == m_pCurrentElement);
632 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty( )
634 bool rc = false;
636 if (m_pCurrentElement->children == nullptr)
638 rc = true;
641 return rc;
644 OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
646 xmlNodePtr pNode = checkElement(node);
647 return OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name));
650 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData(
651 const cssu::Reference< cssxw::XXMLElementWrapper >& node,
652 const cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >& reservedDescendants,
653 const cssu::Reference< cssxw::XXMLElementWrapper >& stopAtNode )
655 xmlNodePtr pTargetNode = checkElement(node);
657 m_pStopAtNode = checkElement(stopAtNode);
658 m_aReservedNodes = reservedDescendants;
659 m_nReservedNodeIndex = 0;
661 getNextReservedNode();
663 recursiveDelete(pTargetNode);
666 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const cssu::Reference< cssxw::XXMLElementWrapper >& node )
668 xmlNodePtr pTargetNode = checkElement(node);
669 xmlNodePtr pParent;
671 while (pTargetNode != nullptr)
673 if (pTargetNode->children != nullptr || pTargetNode == m_pCurrentElement)
675 break;
678 pParent = pTargetNode->parent;
679 removeNode(pTargetNode);
680 pTargetNode = pParent;
684 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const cssu::Reference< cssxs::XDocumentHandler >& handler )
686 if (m_pRootElement != nullptr)
688 xmlNodePtr pTempCurrentElement = m_pCurrentElement;
689 sal_Int32 nTempCurrentPosition = m_nCurrentPosition;
691 m_pCurrentElement = m_pRootElement;
693 m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
695 while(true)
697 switch (m_nCurrentPosition)
699 case NODEPOSITION_STARTELEMENT:
700 sendStartElement(nullptr, handler, m_pCurrentElement);
701 break;
702 case NODEPOSITION_ENDELEMENT:
703 sendEndElement(nullptr, handler, m_pCurrentElement);
704 break;
705 case NODEPOSITION_NORMAL:
706 sendNode(nullptr, handler, m_pCurrentElement);
707 break;
710 if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT ))
712 break;
715 getNextSAXEvent();
718 m_pCurrentElement = pTempCurrentElement;
719 m_nCurrentPosition = nTempCurrentPosition;
723 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents(
724 const cssu::Reference< cssxs::XDocumentHandler >& handler,
725 const cssu::Reference< cssxs::XDocumentHandler >& xEventKeeperHandler,
726 const cssu::Reference< cssxw::XXMLElementWrapper >& startNode,
727 const cssu::Reference< cssxw::XXMLElementWrapper >& endNode )
730 * The first SAX event is the startElement of the startNode
731 * element.
733 bool bHasCurrentElementChild = (m_pCurrentElement->children != nullptr);
735 xmlNodePtr pTempCurrentElement = m_pCurrentElement;
737 m_pCurrentElement = checkElement(startNode);
739 if (m_pCurrentElement->type == XML_ELEMENT_NODE)
741 m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
743 else
745 m_nCurrentPosition = NODEPOSITION_NORMAL;
748 xmlNodePtr pEndNode = checkElement(endNode);
750 cssu::Reference < cssxc::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, cssu::UNO_QUERY );
752 cssu::Reference< cssxs::XDocumentHandler > xHandler = handler;
754 while(true)
756 switch (m_nCurrentPosition)
758 case NODEPOSITION_STARTELEMENT:
759 sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
760 break;
761 case NODEPOSITION_ENDELEMENT:
762 sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
763 break;
764 case NODEPOSITION_NORMAL:
765 sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement);
766 break;
767 default:
768 throw cssu::RuntimeException();
771 if (xSAXEventKeeper->isBlocking())
773 xHandler = nullptr;
776 if (pEndNode == nullptr &&
777 ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) ||
778 (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT)))
780 break;
783 getNextSAXEvent();
786 * If there is an end point specified, then check whether
787 * the current node equals to the end point. If so, stop
788 * generating.
790 if (pEndNode != nullptr && m_pCurrentElement == pEndNode)
792 break;
796 m_pCurrentElement = pTempCurrentElement;
799 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(
800 const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node )
802 xmlNodePtr pNode = checkElement( node );
803 rebuildIDLink(pNode);
807 /* cssxs::XDocumentHandler */
808 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( )
812 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( )
816 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const OUString& aName, const cssu::Reference< cssxs::XAttributeList >& xAttribs )
818 sal_Int32 nLength = xAttribs->getLength();
819 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
821 for (int i = 0; i < nLength; ++i)
823 aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
824 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
827 compressedStartElement(aName, aAttributes);
830 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const OUString& aName )
832 saxHelper.endElement(aName);
833 m_pCurrentElement = saxHelper.getCurrentNode();
836 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const OUString& aChars )
838 saxHelper.characters(aChars);
841 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const OUString& aWhitespaces )
843 saxHelper.ignorableWhitespace(aWhitespaces);
846 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const OUString& aTarget, const OUString& aData )
848 saxHelper.processingInstruction(aTarget, aData);
851 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& )
855 /* XCompressedDocumentHandler */
856 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedStartDocument( )
860 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedEndDocument( )
864 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedStartElement( const OUString& aName, const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
866 saxHelper.startElement(aName, aAttributes);
867 m_pCurrentElement = saxHelper.getCurrentNode();
869 buildIDAttr( m_pCurrentElement );
872 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedEndElement( const OUString& aName )
874 endElement( aName );
877 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedCharacters( const OUString& aChars )
879 characters( aChars );
882 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedIgnorableWhitespace( const OUString& aWhitespaces )
884 ignorableWhitespace( aWhitespaces );
887 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedProcessingInstruction( const OUString& aTarget, const OUString& aData )
889 processingInstruction( aTarget, aData );
892 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedSetDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const OUString& /*publicId*/, const OUString& /*systemId*/ )
896 OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName ()
898 return OUString ( IMPLEMENTATION_NAME );
901 cssu::Sequence< OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames( )
903 cssu::Sequence<OUString> aRet { "com.sun.star.xml.wrapper.XMLDocumentWrapper" };
904 return aRet;
907 cssu::Reference< cssu::XInterface > SAL_CALL XMLDocumentWrapper_XmlSecImpl_createInstance(
908 const cssu::Reference< cssu::XComponentContext > &)
910 return static_cast<cppu::OWeakObject*>(new XMLDocumentWrapper_XmlSecImpl( ));
913 /* XServiceInfo */
914 OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( )
916 return XMLDocumentWrapper_XmlSecImpl_getImplementationName();
918 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const OUString& rServiceName )
920 return cppu::supportsService( this, rServiceName );
922 cssu::Sequence< OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( )
924 return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames();
927 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */