android: Update app icon to new startcenter icon
[LibreOffice.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blobb5a7f027287f9df14fc01a8e9a81e67950eb4b90
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 .
21 #include <framework/saxeventkeeperimpl.hxx>
22 #include "buffernode.hxx"
23 #include "elementmark.hxx"
24 #include "elementcollector.hxx"
25 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
26 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
27 #include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
28 #include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <osl/diagnose.h>
31 #include <rtl/ustrbuf.hxx>
33 #include <algorithm>
35 SAXEventKeeperImpl::SAXEventKeeperImpl( )
36 :m_pCurrentBufferNode(nullptr),
37 m_nNextElementMarkId(1),
38 m_pNewBlocker(nullptr),
39 m_pCurrentBlockingBufferNode(nullptr),
40 m_bIsReleasing(false),
41 m_bIsForwarding(false)
43 m_vElementMarkBuffers.reserve(2);
44 m_vNewElementCollectors.reserve(2);
45 m_vReleasedElementMarkBuffers.reserve(2);
48 SAXEventKeeperImpl::~SAXEventKeeperImpl()
51 * delete the BufferNode tree
53 m_pRootBufferNode.reset();
55 m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = nullptr;
58 * delete all unfreed ElementMarks
60 m_vNewElementCollectors.clear();
61 m_pNewBlocker = nullptr;
64 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
65 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
67 * NAME
68 * setCurrentBufferNode -- set a new active BufferNode.
70 * SYNOPSIS
71 * setCurrentBufferNode( pBufferNode );
73 * FUNCTION
74 * connects this BufferNode into the BufferNode tree as a child of the
75 * current active BufferNode. Then makes this BufferNode as the current
76 * active BufferNode.
77 * If the previous active BufferNode points to the root
78 * BufferNode, which means that no buffering operation was proceeding,
79 * then notifies the status change listener that buffering operation
80 * will begin at once.
82 * INPUTS
83 * pBufferNode - a BufferNode which will be the new active BufferNode
84 ******************************************************************************/
86 if (pBufferNode == m_pCurrentBufferNode)
87 return;
89 if ( m_pCurrentBufferNode == m_pRootBufferNode.get() &&
90 m_xSAXEventKeeperStatusChangeListener.is())
92 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(true);
95 if (pBufferNode->getParent() == nullptr)
97 m_pCurrentBufferNode->addChild(std::unique_ptr<BufferNode>(pBufferNode));
98 pBufferNode->setParent(m_pCurrentBufferNode);
101 m_pCurrentBufferNode = pBufferNode;
104 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
105 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
107 * NAME
108 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
110 * SYNOPSIS
111 * pBufferNode = addNewElementMarkBuffers( );
113 * FUNCTION
114 * if there are new ElementCollector or new Blocker to be added, then
115 * connect all of them with the current BufferNode. In case of the
116 * current BufferNode doesn't exist, creates one.
117 * Clears up the new ElementCollector list and the new Blocker pointer.
119 * RESULT
120 * pBufferNode - the BufferNode that has been connected with both new
121 * ElementCollectors and new Blocker.
122 ******************************************************************************/
124 BufferNode* pBufferNode = nullptr;
126 if (m_pNewBlocker || !m_vNewElementCollectors.empty() )
129 * When the current BufferNode is right pointing to the current
130 * working element in the XMLDocumentWrapper component, then
131 * no new BufferNode is needed to create.
132 * This situation can only happen in the "Forwarding" mode.
134 if ( (m_pCurrentBufferNode != nullptr) &&
135 (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
137 pBufferNode = m_pCurrentBufferNode;
139 else
141 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
144 if (m_pNewBlocker != nullptr)
146 pBufferNode->setBlocker(m_pNewBlocker);
149 * If no blocking before, then notify the status change listener that
150 * the SAXEventKeeper has entered "blocking" status, during which, no
151 * SAX events will be forwarded to the next document handler.
153 if (m_pCurrentBlockingBufferNode == nullptr)
155 m_pCurrentBlockingBufferNode = pBufferNode;
157 if (m_xSAXEventKeeperStatusChangeListener.is())
159 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(true);
163 m_pNewBlocker = nullptr;
166 for( const auto& i : m_vNewElementCollectors )
168 pBufferNode->addElementCollector(i);
170 m_vNewElementCollectors.clear();
173 return pBufferNode;
176 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
177 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
179 * NAME
180 * findElementMarkBuffer -- finds an ElementMark.
182 * SYNOPSIS
183 * pElementMark = findElementMarkBuffer( nId );
185 * FUNCTION
186 * searches an ElementMark with the particular Id in the ElementMark
187 * list.
189 * INPUTS
190 * nId - the Id of the ElementMark to be searched.
192 * RESULT
193 * pElementMark - the ElementMark with the particular Id, or NULL when
194 * no such Id exists.
195 ******************************************************************************/
197 ElementMark* pElementMark = nullptr;
199 for( auto&& ii : m_vElementMarkBuffers )
201 if ( nId == ii->getBufferId())
203 pElementMark = const_cast<ElementMark*>(ii.get());
204 break;
208 return pElementMark;
211 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
212 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
214 * NAME
215 * removeElementMarkBuffer -- removes an ElementMark
217 * SYNOPSIS
218 * removeElementMarkBuffer( nId );
220 * FUNCTION
221 * removes an ElementMark with the particular Id in the ElementMark list.
223 * INPUTS
224 * nId - the Id of the ElementMark to be removed.
225 ******************************************************************************/
227 auto ii = std::find_if(m_vElementMarkBuffers.begin(), m_vElementMarkBuffers.end(),
228 [nId](std::unique_ptr<const ElementMark>& rElementMark) { return nId == rElementMark->getBufferId(); }
230 if (ii == m_vElementMarkBuffers.end())
231 return;
234 * checks whether this ElementMark still in the new ElementCollect array
236 auto jj = std::find_if(m_vNewElementCollectors.begin(), m_vNewElementCollectors.end(),
237 [&ii](const ElementCollector* pElementCollector) { return ii->get() == pElementCollector; }
239 if (jj != m_vNewElementCollectors.end())
240 m_vNewElementCollectors.erase(jj);
243 * checks whether this ElementMark is the new Blocker
245 if (ii->get() == m_pNewBlocker)
247 m_pNewBlocker = nullptr;
250 m_vElementMarkBuffers.erase( ii );
253 OUString SAXEventKeeperImpl::printBufferNode(
254 BufferNode const * pBufferNode, sal_Int32 nIndent) const
255 /****** SAXEventKeeperImpl/printBufferNode ***********************************
257 * NAME
258 * printBufferNode -- retrieves the information of a BufferNode and its
259 * branch.
261 * SYNOPSIS
262 * info = printBufferNode( pBufferNode, nIndent );
264 * FUNCTION
265 * all retrieved information includes:
266 * 1. whether it is the current BufferNode;
267 * 2. whether it is the current blocking BufferNode;
268 * 3. the name of the parent element;
269 * 4. the name of this element;
270 * 5. all ElementCollectors working on this BufferNode;
271 * 6. the Blocker working on this BufferNode;
272 * 7. all child BufferNodes' information.
274 * INPUTS
275 * pBufferNode - the BufferNode from where information will be retrieved.
276 * nIndent - how many space characters prefixed before the output
277 * message.
279 * RESULT
280 * info - the information string
281 ******************************************************************************/
283 OUStringBuffer rc;
285 for ( int i=0; i<nIndent; ++i )
287 rc.append(" ");
290 if (pBufferNode == m_pCurrentBufferNode)
292 rc.append("[%]");
295 if (pBufferNode == m_pCurrentBlockingBufferNode)
297 rc.append("[B]");
300 rc.append(" " + m_xXMLDocument->getNodeName(pBufferNode->getXMLElement()));
302 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
303 if (pParent != nullptr)
305 rc.append("[" + m_xXMLDocument->getNodeName(pParent->getXMLElement()) + "]");
308 rc.append(":EC=" + pBufferNode->printChildren() + " BR=");
310 ElementMark * pBlocker = pBufferNode->getBlocker();
311 if (pBlocker != nullptr)
313 rc.append( OUString::number(pBlocker->getBufferId()) +
314 "(SecId=" + OUString::number( pBlocker->getSecurityId() ) + ") ");
316 rc.append("\n");
318 std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren();
319 for( const auto& jj : vChildren )
321 rc.append(printBufferNode(jj.get(), nIndent+4));
324 return rc.makeStringAndClear();
327 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
328 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode const * pBufferNode)
329 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
331 * NAME
332 * collectChildWorkingElement -- collects a BufferNode's all child
333 * Elements.
335 * SYNOPSIS
336 * list = collectChildWorkingElement( pBufferNode );
338 * INPUTS
339 * pBufferNode - the BufferNode whose child Elements will be collected.
341 * RESULT
342 * list - the child Elements list.
343 ******************************************************************************/
345 std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren();
347 css::uno::Sequence < css::uno::Reference<
348 css::xml::wrapper::XXMLElementWrapper > > aChildrenCollection ( vChildren.size());
350 std::transform(vChildren.begin(), vChildren.end(), aChildrenCollection.getArray(),
351 [](const auto& i) { return i->getXMLElement(); });
353 return aChildrenCollection;
356 void SAXEventKeeperImpl::smashBufferNode(
357 BufferNode* pBufferNode, bool bClearRoot) const
358 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
360 * NAME
361 * smashBufferNode -- removes a BufferNode along with its working
362 * element.
364 * SYNOPSIS
365 * smashBufferNode( pBufferNode, bClearRoot );
367 * FUNCTION
368 * removes the BufferNode's working element from the DOM document, while
369 * reserves all ancestor paths for its child BufferNodes.
370 * when any of the BufferNode's ancestor element is useless, removes it
371 * too.
372 * removes the BufferNode from the BufferNode tree.
374 * INPUTS
375 * pBufferNode - the BufferNode to be removed
376 * bClearRoot - whether the root element also needs to be cleared up.
378 * NOTES
379 * when removing a Blocker's BufferNode, the bClearRoot flag should be
380 * true. Because a Blocker can buffer many SAX events which are not used
381 * by any other ElementCollector or Blocker.
382 * When the bClearRoot is set to true, the root BufferNode will be first
383 * cleared, with a stop flag setting at the next Blocking BufferNode. This
384 * operation can delete all useless buffered SAX events which are only
385 * needed by the Blocker to be deleted.
386 ******************************************************************************/
388 if (pBufferNode->hasAnything())
389 return;
391 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
394 * delete the XML data
396 if (pParent == m_pRootBufferNode.get())
398 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == nullptr);
399 bool bIsBlockInside = false;
400 bool bIsBlockingAfterward = false;
403 * If this is a blocker, then remove any out-element data
404 * which caused by blocking. The removal process will stop
405 * at the next blocker to avoid removing any useful data.
407 if (bClearRoot)
409 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
410 aChildElements = collectChildWorkingElement(m_pRootBufferNode.get());
413 * the clearUselessData only clearup the content in the
414 * node, not the node itself.
416 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
417 aChildElements,
418 bIsNotBlocking?nullptr:
419 (m_pCurrentBlockingBufferNode->getXMLElement()));
422 * remove the node if it is empty, then if its parent is also
423 * empty, remove it, then if the next parent is also empty,
424 * remove it,..., until parent become null.
426 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
430 * if blocking, check the relationship between this BufferNode and
431 * the current blocking BufferNode.
433 if ( !bIsNotBlocking )
436 * the current blocking BufferNode is a descendant of this BufferNode.
438 bIsBlockInside = (nullptr != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
441 * the current blocking BufferNode locates behind this BufferNode in tree
442 * order.
444 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
448 * this BufferNode's working element needs to be deleted only when
449 * 1. there is no blocking, or
450 * 2. the current blocking BufferNode is a descendant of this BufferNode,
451 * (then in the BufferNode's working element, the useless data before the blocking
452 * element should be deleted.) or
453 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
454 * (then the useless data between the blocking element and the working element
455 * should be deleted.).
456 * Otherwise, this working element should not be deleted.
458 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
460 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
461 aChildElements = collectChildWorkingElement(pBufferNode);
464 * the clearUselessData only clearup the content in the
465 * node, not the node itself.
467 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
468 aChildElements,
469 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
470 nullptr);
473 * remove the node if it is empty, then if its parent is also
474 * empty, remove it, then if the next parent is also empty,
475 * remove it,..., until parent become null.
477 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
481 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
483 std::vector< std::unique_ptr<BufferNode> > vChildren = pBufferNode->releaseChildren();
484 pParent->removeChild(pBufferNode); // delete buffernode
486 for( auto& i : vChildren )
488 i->setParent(pParent);
489 pParent->addChild(std::move(i), nIndex);
490 nIndex++;
494 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
495 BufferNode* pStartBufferNode)
496 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
498 * NAME
499 * findNextBlockingBufferNode -- finds the next blocking BufferNode
500 * behind the particular BufferNode.
502 * SYNOPSIS
503 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
505 * INPUTS
506 * pStartBufferNode - the BufferNode from where to search the next
507 * blocking BufferNode.
509 * RESULT
510 * pBufferNode - the next blocking BufferNode, or NULL if no such
511 * BufferNode exists.
512 ******************************************************************************/
514 BufferNode* pNext = nullptr;
516 if (pStartBufferNode != nullptr)
518 pNext = pStartBufferNode;
520 while (nullptr != (pNext = const_cast<BufferNode*>(pNext->getNextNodeByTreeOrder())))
522 if (pNext->getBlocker() != nullptr)
524 break;
529 return pNext;
532 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode)
533 /****** SAXEventKeeperImpl/diffuse *******************************************
535 * NAME
536 * diffuse -- diffuse the notification.
538 * SYNOPSIS
539 * diffuse( pBufferNode );
541 * FUNCTION
542 * diffuse the collecting completion notification from the specific
543 * BufferNode along its parent link, until an ancestor which is not
544 * completely received is met.
546 * INPUTS
547 * pBufferNode - the BufferNode from which the notification will be
548 * diffused.
549 ******************************************************************************/
551 BufferNode* pParent = pBufferNode;
553 while(pParent->isAllReceived())
555 pParent->elementCollectorNotify();
556 pParent = const_cast<BufferNode*>(pParent->getParent());
560 void SAXEventKeeperImpl::releaseElementMarkBuffer()
561 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
563 * NAME
564 * releaseElementMarkBuffer -- releases useless ElementMarks
566 * SYNOPSIS
567 * releaseElementMarkBuffer( );
569 * FUNCTION
570 * releases each ElementMark in the releasing list
571 * m_vReleasedElementMarkBuffers.
572 * The operation differs between an ElementCollector and a Blocker.
573 ******************************************************************************/
575 m_bIsReleasing = true;
576 while (!m_vReleasedElementMarkBuffers.empty())
578 auto pId = m_vReleasedElementMarkBuffers.begin();
579 sal_Int32 nId = *pId;
580 m_vReleasedElementMarkBuffers.erase( pId );
582 ElementMark* pElementMark = findElementMarkBuffer(nId);
584 if (pElementMark != nullptr)
586 if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR
587 == pElementMark->getType())
589 * it is a EC
592 ElementCollector* pElementCollector = static_cast<ElementCollector*>(pElementMark);
594 css::xml::crypto::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
596 * Delete the EC from the buffer node.
598 BufferNode* pBufferNode = pElementCollector->getBufferNode();
599 pBufferNode->removeElementCollector(pElementCollector);
601 if ( nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY)
603 pBufferNode->notifyBranch();
607 * delete the ElementMark
609 pElementCollector = nullptr;
610 pElementMark = nullptr;
611 removeElementMarkBuffer(nId);
614 * delete the BufferNode
616 diffuse(pBufferNode);
617 smashBufferNode(pBufferNode, false);
619 else
621 * it is a Blocker
625 * Delete the TH from the buffer node.
627 BufferNode *pBufferNode = pElementMark->getBufferNode();
628 pBufferNode->setBlocker(nullptr);
631 * If there is a following handler and no blocking now, then
632 * forward this event
634 if (m_pCurrentBlockingBufferNode == pBufferNode)
637 * Before forwarding, the next blocking point needs to be
638 * found.
640 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
643 * Forward the blocked events between these two STHs.
645 if (m_xNextHandler.is())
647 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
648 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
650 m_pCurrentBufferNode = pBufferNode;
651 m_pCurrentBlockingBufferNode = nullptr;
653 m_bIsForwarding = true;
655 m_xXMLDocument->generateSAXEvents(
656 m_xNextHandler,
657 this,
658 pBufferNode->getXMLElement(),
659 (pTempCurrentBlockingBufferNode == nullptr)?nullptr:(pTempCurrentBlockingBufferNode->getXMLElement()));
661 m_bIsForwarding = false;
663 m_pCurrentBufferNode = pTempCurrentBufferNode;
664 if (m_pCurrentBlockingBufferNode == nullptr)
666 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
670 if (m_pCurrentBlockingBufferNode == nullptr &&
671 m_xSAXEventKeeperStatusChangeListener.is())
673 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(false);
678 * delete the ElementMark
680 pElementMark = nullptr;
681 removeElementMarkBuffer(nId);
684 * delete the BufferNode
686 diffuse(pBufferNode);
687 smashBufferNode(pBufferNode, true);
692 m_bIsReleasing = false;
694 if (!m_pRootBufferNode->hasAnything() &&
695 !m_pRootBufferNode->hasChildren() &&
696 m_xSAXEventKeeperStatusChangeListener.is())
698 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(true);
702 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
703 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
705 * NAME
706 * markElementMarkBuffer -- marks an ElementMark to be released
708 * SYNOPSIS
709 * markElementMarkBuffer( nId );
711 * FUNCTION
712 * puts the ElementMark with the particular Id into the releasing list,
713 * checks whether the releasing process is running, if not then launch
714 * this process.
716 * INPUTS
717 * nId - the Id of the ElementMark which will be released
718 ******************************************************************************/
720 m_vReleasedElementMarkBuffers.push_back( nId );
721 if ( !m_bIsReleasing )
723 releaseElementMarkBuffer();
727 sal_Int32 SAXEventKeeperImpl::createElementCollector(
728 css::xml::crypto::sax::ElementMarkPriority nPriority,
729 bool bModifyElement,
730 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
731 /****** SAXEventKeeperImpl/createElementCollector ****************************
733 * NAME
734 * createElementCollector -- creates a new ElementCollector on the
735 * incoming element.
737 * SYNOPSIS
738 * nId = createElementCollector( nSecurityId, nPriority,
739 * bModifyElement,
740 * xReferenceResolvedListener );
742 * FUNCTION
743 * allocs a new Id, then create an ElementCollector with this Id value.
744 * Add the new created ElementCollector to the new ElementCollecotor list.
746 * INPUTS
747 * nPriority - the priority of the new ElementCollector
748 * bModifyElement -whether this BufferNode will modify the content of
749 * the corresponding element it works on
750 * xReferenceResolvedListener - the listener for the new ElementCollector.
752 * RESULT
753 * nId - the Id of the new ElementCollector
754 ******************************************************************************/
756 sal_Int32 nId = m_nNextElementMarkId;
757 m_nNextElementMarkId ++;
759 ElementCollector* pElementCollector
760 = new ElementCollector(
761 nId,
762 nPriority,
763 bModifyElement,
764 xReferenceResolvedListener);
766 m_vElementMarkBuffers.push_back(
767 std::unique_ptr<const ElementMark>(pElementCollector));
770 * All the new EC to initial EC array.
772 m_vNewElementCollectors.push_back( pElementCollector );
774 return nId;
778 sal_Int32 SAXEventKeeperImpl::createBlocker()
779 /****** SAXEventKeeperImpl/createBlocker *************************************
781 * NAME
782 * createBlocker -- creates a new Blocker on the incoming element.
784 * SYNOPSIS
785 * nId = createBlocker( nSecurityId );
787 * RESULT
788 * nId - the Id of the new Blocker
789 ******************************************************************************/
791 sal_Int32 nId = m_nNextElementMarkId;
792 m_nNextElementMarkId ++;
794 OSL_ASSERT(m_pNewBlocker == nullptr);
796 m_pNewBlocker = new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId);
797 m_vElementMarkBuffers.push_back(
798 std::unique_ptr<const ElementMark>(m_pNewBlocker));
800 return nId;
803 /* XSAXEventKeeper */
804 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
806 return createElementCollector(
807 css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY,
808 false,
809 nullptr);
812 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
814 markElementMarkBuffer(id);
817 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
819 return createBlocker();
822 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
824 markElementMarkBuffer(id);
827 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
829 return (m_pCurrentBlockingBufferNode != nullptr);
832 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL
833 SAXEventKeeperImpl::getElement( sal_Int32 id )
835 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
837 ElementMark* pElementMark = findElementMarkBuffer(id);
838 if (pElementMark != nullptr)
840 rc = pElementMark->getBufferNode()->getXMLElement();
843 return rc;
846 void SAL_CALL SAXEventKeeperImpl::setElement(
847 sal_Int32 id,
848 const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement )
850 if (aElement.is())
852 m_xXMLDocument->rebuildIDLink(aElement);
854 ElementMark* pElementMark = findElementMarkBuffer(id);
856 if (pElementMark != nullptr)
858 BufferNode* pBufferNode = pElementMark->getBufferNode();
859 if (pBufferNode != nullptr)
861 const bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
862 pBufferNode->setXMLElement(aElement);
864 if (bIsCurrent)
866 m_xXMLDocument->setCurrentElement(aElement);
871 else
873 removeElementCollector( id );
877 css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
878 const css::uno::Reference< css::xml::sax::XDocumentHandler >& xNewHandler )
880 css::uno::Reference< css::xml::sax::XDocumentHandler > xOldHandler = m_xNextHandler;
882 m_xNextHandler = xNewHandler;
883 return xOldHandler;
886 OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
888 OUString rc = "ElementMarkBuffers: size = "
889 + OUString::number(m_vElementMarkBuffers.size())
890 + "\nCurrentBufferNode: "
891 + m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement())
892 + "\n" + printBufferNode(m_pRootBufferNode.get(), 0);
894 return rc;
897 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
899 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
901 if (m_pCurrentBlockingBufferNode != nullptr)
903 rc = m_pCurrentBlockingBufferNode->getXMLElement();
906 return rc;
909 /* XSecuritySAXEventKeeper */
910 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
911 css::xml::crypto::sax::ElementMarkPriority priority,
912 sal_Bool modifyElement )
914 return createElementCollector(
915 priority,
916 modifyElement,
917 nullptr);
920 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
922 ElementMark* pElementMark = findElementMarkBuffer(id);
923 if (pElementMark != nullptr)
925 pElementMark->setSecurityId(securityId);
930 /* XReferenceResolvedBroadcaster */
931 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
932 sal_Int32 referenceId,
933 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener )
935 ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId));
936 if (pElementCollector != nullptr)
938 pElementCollector->setReferenceResolvedListener(listener);
942 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
943 sal_Int32 /*referenceId*/,
944 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >&)
948 /* XSAXEventKeeperStatusChangeBroadcaster */
949 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
950 const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener )
952 m_xSAXEventKeeperStatusChangeListener = listener;
955 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
956 const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >&)
960 /* XDocumentHandler */
961 void SAL_CALL SAXEventKeeperImpl::startDocument( )
963 if ( m_xNextHandler.is())
965 m_xNextHandler->startDocument();
969 void SAL_CALL SAXEventKeeperImpl::endDocument( )
971 if ( m_xNextHandler.is())
973 m_xNextHandler->endDocument();
977 void SAL_CALL SAXEventKeeperImpl::startElement(
978 const OUString& aName,
979 const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
982 * If there is a following handler and no blocking now, then
983 * forward this event
985 if ((m_pCurrentBlockingBufferNode == nullptr) &&
986 (m_xNextHandler.is()) &&
987 (!m_bIsForwarding) &&
988 (m_pNewBlocker == nullptr))
990 m_xNextHandler->startElement(aName, xAttribs);
993 * If not forwarding, buffer this startElement.
995 if (!m_bIsForwarding)
997 sal_Int32 nLength = xAttribs->getLength();
998 css::uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength);
999 auto aAttributesRange = asNonConstRange(aAttributes);
1001 for ( int i = 0; i<nLength; ++i )
1003 aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i));
1004 aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i));
1007 m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes);
1010 BufferNode* pBufferNode = addNewElementMarkBuffers();
1011 if (pBufferNode != nullptr)
1013 setCurrentBufferNode(pBufferNode);
1017 void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName )
1019 const bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1022 * If there is a following handler and no blocking now, then
1023 * forward this event
1025 if ((m_pCurrentBlockingBufferNode == nullptr) &&
1026 (m_xNextHandler.is()) &&
1027 (!m_bIsForwarding))
1029 m_xNextHandler->endElement(aName);
1032 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1033 (m_pCurrentBufferNode != m_pRootBufferNode.get()) ||
1034 (!m_xXMLDocument->isCurrentElementEmpty()))
1036 if (!m_bIsForwarding)
1038 m_xCompressedDocumentHandler->compressedEndElement(aName);
1042 * If the current buffer node has not notified yet, and
1043 * the current buffer node is waiting for the current element,
1044 * then let it notify.
1046 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1048 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1049 m_pCurrentBufferNode = const_cast<BufferNode*>(m_pCurrentBufferNode->getParent());
1051 pOldCurrentBufferNode->setReceivedAll();
1053 if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) &&
1054 m_xSAXEventKeeperStatusChangeListener.is())
1056 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false);
1060 else
1062 if (!m_bIsForwarding)
1064 m_xXMLDocument->removeCurrentElement();
1069 void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars )
1071 if (m_bIsForwarding)
1072 return;
1074 if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
1076 m_xNextHandler->characters(aChars);
1079 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1080 (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1082 m_xCompressedDocumentHandler->compressedCharacters(aChars);
1086 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces )
1088 characters( aWhitespaces );
1091 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1092 const OUString& aTarget, const OUString& aData )
1094 if (m_bIsForwarding)
1095 return;
1097 if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
1099 m_xNextHandler->processingInstruction(aTarget, aData);
1102 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1103 (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1105 m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData);
1109 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&)
1113 /* XInitialization */
1114 void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
1116 OSL_ASSERT(aArguments.getLength() == 1);
1118 aArguments[0] >>= m_xXMLDocument;
1119 m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
1120 m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
1122 m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) );
1123 m_pCurrentBufferNode = m_pRootBufferNode.get();
1126 OUString SAXEventKeeperImpl_getImplementationName ()
1128 return "com.sun.star.xml.security.framework.SAXEventKeeperImpl";
1131 css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( )
1133 return { "com.sun.star.xml.crypto.sax.SAXEventKeeper" };
1136 /* XServiceInfo */
1137 OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
1139 return SAXEventKeeperImpl_getImplementationName();
1142 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName )
1144 return cppu::supportsService(this, rServiceName);
1147 css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1149 return SAXEventKeeperImpl_getSupportedServiceNames();
1152 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */