/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include "buffernode.hxx" #include "elementmark.hxx" #include "elementcollector.hxx" #include #include #include #include #include #include #include #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl" SAXEventKeeperImpl::SAXEventKeeperImpl( ) :m_pCurrentBufferNode(nullptr), m_nNextElementMarkId(1), m_pNewBlocker(nullptr), m_pCurrentBlockingBufferNode(nullptr), m_bIsReleasing(false), m_bIsForwarding(false) { m_vElementMarkBuffers.reserve(2); m_vNewElementCollectors.reserve(2); m_vReleasedElementMarkBuffers.reserve(2); } SAXEventKeeperImpl::~SAXEventKeeperImpl() { /* * delete the BufferNode tree */ m_pRootBufferNode.reset(); m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = nullptr; /* * delete all unfreed ElementMarks */ m_vNewElementCollectors.clear(); m_pNewBlocker = nullptr; } void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode) /****** SAXEventKeeperImpl/setCurrentBufferNode ****************************** * * NAME * setCurrentBufferNode -- set a new active BufferNode. * * SYNOPSIS * setCurrentBufferNode( pBufferNode ); * * FUNCTION * connects this BufferNode into the BufferNode tree as a child of the * current active BufferNode. Then makes this BufferNode as the current * active BufferNode. * If the previous active BufferNode points to the root * BufferNode, which means that no buffering operation was proceeding, * then notifies the status change listener that buffering operation * will begin at once. * * INPUTS * pBufferNode - a BufferNode which will be the new active BufferNode ******************************************************************************/ { if (pBufferNode == m_pCurrentBufferNode) return; if ( m_pCurrentBufferNode == m_pRootBufferNode.get() && m_xSAXEventKeeperStatusChangeListener.is()) { m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(true); } if (pBufferNode->getParent() == nullptr) { m_pCurrentBufferNode->addChild(std::unique_ptr(pBufferNode)); pBufferNode->setParent(m_pCurrentBufferNode); } m_pCurrentBufferNode = pBufferNode; } BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers() /****** SAXEventKeeperImpl/addNewElementMarkBuffers ************************** * * NAME * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker. * * SYNOPSIS * pBufferNode = addNewElementMarkBuffers( ); * * FUNCTION * if there are new ElementCollector or new Blocker to be added, then * connect all of them with the current BufferNode. In case of the * current BufferNode doesn't exist, creates one. * Clears up the new ElementCollector list and the new Blocker pointer. * * RESULT * pBufferNode - the BufferNode that has been connected with both new * ElementCollectors and new Blocker. ******************************************************************************/ { BufferNode* pBufferNode = nullptr; if (m_pNewBlocker || !m_vNewElementCollectors.empty() ) { /* * When the current BufferNode is right pointing to the current * working element in the XMLDocumentWrapper component, then * no new BufferNode is needed to create. * This situation can only happen in the "Forwarding" mode. */ if ( (m_pCurrentBufferNode != nullptr) && (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement()))) { pBufferNode = m_pCurrentBufferNode; } else { pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement()); } if (m_pNewBlocker != nullptr) { pBufferNode->setBlocker(m_pNewBlocker); /* * If no blocking before, then notify the status change listener that * the SAXEventKeeper has entered "blocking" status, during which, no * SAX events will be forwarded to the next document handler. */ if (m_pCurrentBlockingBufferNode == nullptr) { m_pCurrentBlockingBufferNode = pBufferNode; if (m_xSAXEventKeeperStatusChangeListener.is()) { m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(true); } } m_pNewBlocker = nullptr; } for( const auto& i : m_vNewElementCollectors ) { pBufferNode->addElementCollector(i); } m_vNewElementCollectors.clear(); } return pBufferNode; } ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const /****** SAXEventKeeperImpl/findElementMarkBuffer ***************************** * * NAME * findElementMarkBuffer -- finds an ElementMark. * * SYNOPSIS * pElementMark = findElementMarkBuffer( nId ); * * FUNCTION * searches an ElementMark with the particular Id in the ElementMark * list. * * INPUTS * nId - the Id of the ElementMark to be searched. * * RESULT * pElementMark - the ElementMark with the particular Id, or NULL when * no such Id exists. ******************************************************************************/ { ElementMark* pElementMark = nullptr; for( auto&& ii : m_vElementMarkBuffers ) { if ( nId == ii->getBufferId()) { pElementMark = const_cast(ii.get()); break; } } return pElementMark; } void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId) /****** SAXEventKeeperImpl/removeElementMarkBuffer *************************** * * NAME * removeElementMarkBuffer -- removes an ElementMark * * SYNOPSIS * removeElementMarkBuffer( nId ); * * FUNCTION * removes an ElementMark with the particular Id in the ElementMark list. * * INPUTS * nId - the Id of the ElementMark to be removed. ******************************************************************************/ { auto ii = std::find_if(m_vElementMarkBuffers.begin(), m_vElementMarkBuffers.end(), [nId](std::unique_ptr& rElementMark) { return nId == rElementMark->getBufferId(); } ); if (ii == m_vElementMarkBuffers.end()) return; /* * checks whether this ElementMark still in the new ElementCollect array */ auto jj = std::find_if(m_vNewElementCollectors.begin(), m_vNewElementCollectors.end(), [&ii](const ElementCollector* pElementCollector) { return ii->get() == pElementCollector; } ); if (jj != m_vNewElementCollectors.end()) m_vNewElementCollectors.erase(jj); /* * checks whether this ElementMark is the new Blocker */ if (ii->get() == m_pNewBlocker) { m_pNewBlocker = nullptr; } m_vElementMarkBuffers.erase( ii ); } OUString SAXEventKeeperImpl::printBufferNode( BufferNode const * pBufferNode, sal_Int32 nIndent) const /****** SAXEventKeeperImpl/printBufferNode *********************************** * * NAME * printBufferNode -- retrieves the information of a BufferNode and its * branch. * * SYNOPSIS * info = printBufferNode( pBufferNode, nIndent ); * * FUNCTION * all retrieved information includes: * 1. whether it is the current BufferNode; * 2. whether it is the current blocking BufferNode; * 3. the name of the parent element; * 4. the name of this element; * 5. all ElementCollectors working on this BufferNode; * 6. the Blocker working on this BufferNode; * 7. all child BufferNodes' information. * * INPUTS * pBufferNode - the BufferNode from where information will be retrieved. * nIndent - how many space characters prefixed before the output * message. * * RESULT * info - the information string ******************************************************************************/ { OUStringBuffer rc; for ( int i=0; igetNodeName(pBufferNode->getXMLElement())); BufferNode* pParent = const_cast(pBufferNode->getParent()); if (pParent != nullptr) { rc.append("[").append(m_xXMLDocument->getNodeName(pParent->getXMLElement())).append("]"); } rc.append(":EC=").append(pBufferNode->printChildren()).append(" BR="); ElementMark * pBlocker = pBufferNode->getBlocker(); if (pBlocker != nullptr) { rc.append(OUString::number( pBlocker->getBufferId() )).append("(SecId=") .append(OUString::number( pBlocker->getSecurityId() )).append(") "); } rc.append("\n"); std::vector< std::unique_ptr > const & vChildren = pBufferNode->getChildren(); for( const auto& jj : vChildren ) { rc.append(printBufferNode(jj.get(), nIndent+4)); } return rc.makeStringAndClear(); } css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAXEventKeeperImpl::collectChildWorkingElement(BufferNode const * pBufferNode) /****** SAXEventKeeperImpl/collectChildWorkingElement ************************ * * NAME * collectChildWorkingElement -- collects a BufferNode's all child * Elements. * * SYNOPSIS * list = collectChildWorkingElement( pBufferNode ); * * INPUTS * pBufferNode - the BufferNode whose child Elements will be collected. * * RESULT * list - the child Elements list. ******************************************************************************/ { std::vector< std::unique_ptr > const & vChildren = pBufferNode->getChildren(); css::uno::Sequence < css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > aChildrenCollection ( vChildren.size()); sal_Int32 nIndex = 0; for( const auto& i : vChildren ) { aChildrenCollection[nIndex] = i->getXMLElement(); nIndex++; } return aChildrenCollection; } void SAXEventKeeperImpl::smashBufferNode( BufferNode* pBufferNode, bool bClearRoot) const /****** SAXEventKeeperImpl/smashBufferNode *********************************** * * NAME * smashBufferNode -- removes a BufferNode along with its working * element. * * SYNOPSIS * smashBufferNode( pBufferNode, bClearRoot ); * * FUNCTION * removes the BufferNode's working element from the DOM document, while * reserves all ancestor paths for its child BufferNodes. * when any of the BufferNode's ancestor element is useless, removes it * too. * removes the BufferNode from the BufferNode tree. * * INPUTS * pBufferNode - the BufferNode to be removed * bClearRoot - whether the root element also needs to be cleared up. * * NOTES * when removing a Blocker's BufferNode, the bClearRoot flag should be * true. Because a Blocker can buffer many SAX events which are not used * by any other ElementCollector or Blocker. * When the bClearRoot is set to true, the root BufferNode will be first * cleared, with a stop flag setting at the next Blocking BufferNode. This * operation can delete all useless buffered SAX events which are only * needed by the Blocker to be deleted. ******************************************************************************/ { if (pBufferNode->hasAnything()) return; BufferNode* pParent = const_cast(pBufferNode->getParent()); /* * delete the XML data */ if (pParent == m_pRootBufferNode.get()) { bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == nullptr); bool bIsBlockInside = false; bool bIsBlockingAfterward = false; /* * If this is a blocker, then remove any out-element data * which caused by blocking. The removal process will stop * at the next blocker to avoid removing any useful data. */ if (bClearRoot) { css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > aChildElements = collectChildWorkingElement(m_pRootBufferNode.get()); /* * the clearUselessData only clearup the content in the * node, not the node itself. */ m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(), aChildElements, bIsNotBlocking?nullptr: (m_pCurrentBlockingBufferNode->getXMLElement())); /* * remove the node if it is empty, then if its parent is also * empty, remove it, then if the next parent is also empty, * remove it,..., until parent become null. */ m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() ); } /* * if blocking, check the relationship between this BufferNode and * the current blocking BufferNode. */ if ( !bIsNotBlocking ) { /* * the current blocking BufferNode is a descendant of this BufferNode. */ bIsBlockInside = (nullptr != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode)); /* * the current blocking BufferNode locates behind this BufferNode in tree * order. */ bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode); } /* * this BufferNode's working element needs to be deleted only when * 1. there is no blocking, or * 2. the current blocking BufferNode is a descendant of this BufferNode, * (then in the BufferNode's working element, the useless data before the blocking * element should be deleted.) or * 3. the current blocking BufferNode is locates behind this BufferNode in tree, * (then the useless data between the blocking element and the working element * should be deleted.). * Otherwise, this working element should not be deleted. */ if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward ) { css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > aChildElements = collectChildWorkingElement(pBufferNode); /* * the clearUselessData only clearup the content in the * node, not the node itself. */ m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(), aChildElements, bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()): nullptr); /* * remove the node if it is empty, then if its parent is also * empty, remove it, then if the next parent is also empty, * remove it,..., until parent become null. */ m_xXMLDocument->collapse( pBufferNode->getXMLElement() ); } } sal_Int32 nIndex = pParent->indexOfChild(pBufferNode); std::vector< std::unique_ptr > vChildren = pBufferNode->releaseChildren(); pParent->removeChild(pBufferNode); // delete buffernode for( auto& i : vChildren ) { i->setParent(pParent); pParent->addChild(std::move(i), nIndex); nIndex++; } } BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode( BufferNode* pStartBufferNode) /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************ * * NAME * findNextBlockingBufferNode -- finds the next blocking BufferNode * behind the particular BufferNode. * * SYNOPSIS * pBufferNode = findNextBlockingBufferNode( pStartBufferNode ); * * INPUTS * pStartBufferNode - the BufferNode from where to search the next * blocking BufferNode. * * RESULT * pBufferNode - the next blocking BufferNode, or NULL if no such * BufferNode exists. ******************************************************************************/ { BufferNode* pNext = nullptr; if (pStartBufferNode != nullptr) { pNext = pStartBufferNode; while (nullptr != (pNext = const_cast(pNext->getNextNodeByTreeOrder()))) { if (pNext->getBlocker() != nullptr) { break; } } } return pNext; } void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) /****** SAXEventKeeperImpl/diffuse ******************************************* * * NAME * diffuse -- diffuse the notification. * * SYNOPSIS * diffuse( pBufferNode ); * * FUNCTION * diffuse the collecting completion notification from the specific * BufferNode along its parent link, until an ancestor which is not * completely received is met. * * INPUTS * pBufferNode - the BufferNode from which the notification will be * diffused. ******************************************************************************/ { BufferNode* pParent = pBufferNode; while(pParent->isAllReceived()) { pParent->elementCollectorNotify(); pParent = const_cast(pParent->getParent()); } } void SAXEventKeeperImpl::releaseElementMarkBuffer() /****** SAXEventKeeperImpl/releaseElementMarkBuffer ************************** * * NAME * releaseElementMarkBuffer -- releases useless ElementMarks * * SYNOPSIS * releaseElementMarkBuffer( ); * * FUNCTION * releases each ElementMark in the releasing list * m_vReleasedElementMarkBuffers. * The operation differs between an ElementCollector and a Blocker. ******************************************************************************/ { m_bIsReleasing = true; while (!m_vReleasedElementMarkBuffers.empty()) { auto pId = m_vReleasedElementMarkBuffers.begin(); sal_Int32 nId = *pId; m_vReleasedElementMarkBuffers.erase( pId ); ElementMark* pElementMark = findElementMarkBuffer(nId); if (pElementMark != nullptr) { if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR == pElementMark->getType()) /* * it is a EC */ { ElementCollector* pElementCollector = static_cast(pElementMark); css::xml::crypto::sax::ElementMarkPriority nPriority = pElementCollector->getPriority(); /* * Delete the EC from the buffer node. */ BufferNode* pBufferNode = pElementCollector->getBufferNode(); pBufferNode->removeElementCollector(pElementCollector); if ( nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY) { pBufferNode->notifyBranch(); } /* * delete the ElementMark */ pElementCollector = nullptr; pElementMark = nullptr; removeElementMarkBuffer(nId); /* * delete the BufferNode */ diffuse(pBufferNode); smashBufferNode(pBufferNode, false); } else /* * it is a Blocker */ { /* * Delete the TH from the buffer node. */ BufferNode *pBufferNode = pElementMark->getBufferNode(); pBufferNode->setBlocker(nullptr); /* * If there is a following handler and no blocking now, then * forward this event */ if (m_pCurrentBlockingBufferNode == pBufferNode) { /* * Before forwarding, the next blocking point needs to be * found. */ m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode); /* * Forward the blocked events between these two STHs. */ if (m_xNextHandler.is()) { BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode; BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode; m_pCurrentBufferNode = pBufferNode; m_pCurrentBlockingBufferNode = nullptr; m_bIsForwarding = true; m_xXMLDocument->generateSAXEvents( m_xNextHandler, this, pBufferNode->getXMLElement(), (pTempCurrentBlockingBufferNode == nullptr)?nullptr:(pTempCurrentBlockingBufferNode->getXMLElement())); m_bIsForwarding = false; m_pCurrentBufferNode = pTempCurrentBufferNode; if (m_pCurrentBlockingBufferNode == nullptr) { m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode; } } if (m_pCurrentBlockingBufferNode == nullptr && m_xSAXEventKeeperStatusChangeListener.is()) { m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(false); } } /* * delete the ElementMark */ pElementMark = nullptr; removeElementMarkBuffer(nId); /* * delete the BufferNode */ diffuse(pBufferNode); smashBufferNode(pBufferNode, true); } } } m_bIsReleasing = false; if (!m_pRootBufferNode->hasAnything() && !m_pRootBufferNode->hasChildren() && m_xSAXEventKeeperStatusChangeListener.is()) { m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(true); } } void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId) /****** SAXEventKeeperImpl/markElementMarkBuffer ***************************** * * NAME * markElementMarkBuffer -- marks an ElementMark to be released * * SYNOPSIS * markElementMarkBuffer( nId ); * * FUNCTION * puts the ElementMark with the particular Id into the releasing list, * checks whether the releasing process is running, if not then launch * this process. * * INPUTS * nId - the Id of the ElementMark which will be released ******************************************************************************/ { m_vReleasedElementMarkBuffers.push_back( nId ); if ( !m_bIsReleasing ) { releaseElementMarkBuffer(); } } sal_Int32 SAXEventKeeperImpl::createElementCollector( css::xml::crypto::sax::ElementMarkPriority nPriority, bool bModifyElement, const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener) /****** SAXEventKeeperImpl/createElementCollector **************************** * * NAME * createElementCollector -- creates a new ElementCollector on the * incoming element. * * SYNOPSIS * nId = createElementCollector( nSecurityId, nPriority, * bModifyElement, * xReferenceResolvedListener ); * * FUNCTION * allocs a new Id, then create an ElementCollector with this Id value. * Add the new created ElementCollector to the new ElementCollecotor list. * * INPUTS * nPriority - the priority of the new ElementCollector * bModifyElement -whether this BufferNode will modify the content of * the corresponding element it works on * xReferenceResolvedListener - the listener for the new ElementCollector. * * RESULT * nId - the Id of the new ElementCollector ******************************************************************************/ { sal_Int32 nId = m_nNextElementMarkId; m_nNextElementMarkId ++; ElementCollector* pElementCollector = new ElementCollector( nId, nPriority, bModifyElement, xReferenceResolvedListener); m_vElementMarkBuffers.push_back( std::unique_ptr(pElementCollector)); /* * All the new EC to initial EC array. */ m_vNewElementCollectors.push_back( pElementCollector ); return nId; } sal_Int32 SAXEventKeeperImpl::createBlocker() /****** SAXEventKeeperImpl/createBlocker ************************************* * * NAME * createBlocker -- creates a new Blocker on the incoming element. * * SYNOPSIS * nId = createBlocker( nSecurityId ); * * RESULT * nId - the Id of the new Blocker ******************************************************************************/ { sal_Int32 nId = m_nNextElementMarkId; m_nNextElementMarkId ++; OSL_ASSERT(m_pNewBlocker == nullptr); m_pNewBlocker = new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId); m_vElementMarkBuffers.push_back( std::unique_ptr(m_pNewBlocker)); return nId; } /* XSAXEventKeeper */ sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( ) { return createElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, false, nullptr); } void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id ) { markElementMarkBuffer(id); } sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( ) { return createBlocker(); } void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id ) { markElementMarkBuffer(id); } sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( ) { return (m_pCurrentBlockingBufferNode != nullptr); } css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getElement( sal_Int32 id ) { css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc; ElementMark* pElementMark = findElementMarkBuffer(id); if (pElementMark != nullptr) { rc = pElementMark->getBufferNode()->getXMLElement(); } return rc; } void SAL_CALL SAXEventKeeperImpl::setElement( sal_Int32 id, const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement ) { if (aElement.is()) { m_xXMLDocument->rebuildIDLink(aElement); ElementMark* pElementMark = findElementMarkBuffer(id); if (pElementMark != nullptr) { BufferNode* pBufferNode = pElementMark->getBufferNode(); if (pBufferNode != nullptr) { const bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement()); pBufferNode->setXMLElement(aElement); if (bIsCurrent) { m_xXMLDocument->setCurrentElement(aElement); } } } } else { removeElementCollector( id ); } } css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler( const css::uno::Reference< css::xml::sax::XDocumentHandler >& xNewHandler ) { css::uno::Reference< css::xml::sax::XDocumentHandler > xOldHandler = m_xNextHandler; m_xNextHandler = xNewHandler; return xOldHandler; } OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree() { OUString rc = "ElementMarkBuffers: size = " + OUString::number(m_vElementMarkBuffers.size()) + "\nCurrentBufferNode: " + m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement()) + "\n" + printBufferNode(m_pRootBufferNode.get(), 0); return rc; } css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode() { css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc; if (m_pCurrentBlockingBufferNode != nullptr) { rc = m_pCurrentBlockingBufferNode->getXMLElement(); } return rc; } /* XSecuritySAXEventKeeper */ sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority priority, sal_Bool modifyElement ) { return createElementCollector( priority, modifyElement, nullptr); } void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId ) { ElementMark* pElementMark = findElementMarkBuffer(id); if (pElementMark != nullptr) { pElementMark->setSecurityId(securityId); } } /* XReferenceResolvedBroadcaster */ void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener( sal_Int32 referenceId, const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) { ElementCollector* pElementCollector = static_cast(findElementMarkBuffer(referenceId)); if (pElementCollector != nullptr) { pElementCollector->setReferenceResolvedListener(listener); } } void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener( sal_Int32 /*referenceId*/, const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >&) { } /* XSAXEventKeeperStatusChangeBroadcaster */ void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener( const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) { m_xSAXEventKeeperStatusChangeListener = listener; } void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener( const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >&) { } /* XDocumentHandler */ void SAL_CALL SAXEventKeeperImpl::startDocument( ) { if ( m_xNextHandler.is()) { m_xNextHandler->startDocument(); } } void SAL_CALL SAXEventKeeperImpl::endDocument( ) { if ( m_xNextHandler.is()) { m_xNextHandler->endDocument(); } } void SAL_CALL SAXEventKeeperImpl::startElement( const OUString& aName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) { /* * If there is a following handler and no blocking now, then * forward this event */ if ((m_pCurrentBlockingBufferNode == nullptr) && (m_xNextHandler.is()) && (!m_bIsForwarding) && (m_pNewBlocker == nullptr)) { m_xNextHandler->startElement(aName, xAttribs); } /* * If not forwarding, buffer this startElement. */ if (!m_bIsForwarding) { sal_Int32 nLength = xAttribs->getLength(); css::uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength); for ( int i = 0; igetNameByIndex(static_cast(i)); aAttributes[i].sValue =xAttribs->getValueByIndex(static_cast(i)); } m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes); } BufferNode* pBufferNode = addNewElementMarkBuffers(); if (pBufferNode != nullptr) { setCurrentBufferNode(pBufferNode); } } void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName ) { const bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement()); /* * If there is a following handler and no blocking now, then * forward this event */ if ((m_pCurrentBlockingBufferNode == nullptr) && (m_xNextHandler.is()) && (!m_bIsForwarding)) { m_xNextHandler->endElement(aName); } if ((m_pCurrentBlockingBufferNode != nullptr) || (m_pCurrentBufferNode != m_pRootBufferNode.get()) || (!m_xXMLDocument->isCurrentElementEmpty())) { if (!m_bIsForwarding) { m_xCompressedDocumentHandler->compressedEndElement(aName); } /* * If the current buffer node has not notified yet, and * the current buffer node is waiting for the current element, * then let it notify. */ if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode.get())) { BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode; m_pCurrentBufferNode = const_cast(m_pCurrentBufferNode->getParent()); pOldCurrentBufferNode->setReceivedAll(); if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) && m_xSAXEventKeeperStatusChangeListener.is()) { m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false); } } } else { if (!m_bIsForwarding) { m_xXMLDocument->removeCurrentElement(); } } } void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars ) { if (m_bIsForwarding) return; if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is()) { m_xNextHandler->characters(aChars); } if ((m_pCurrentBlockingBufferNode != nullptr) || (m_pCurrentBufferNode != m_pRootBufferNode.get())) { m_xCompressedDocumentHandler->compressedCharacters(aChars); } } void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces ) { characters( aWhitespaces ); } void SAL_CALL SAXEventKeeperImpl::processingInstruction( const OUString& aTarget, const OUString& aData ) { if (m_bIsForwarding) return; if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is()) { m_xNextHandler->processingInstruction(aTarget, aData); } if ((m_pCurrentBlockingBufferNode != nullptr) || (m_pCurrentBufferNode != m_pRootBufferNode.get())) { m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData); } } void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&) { } /* XInitialization */ void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) { OSL_ASSERT(aArguments.getLength() == 1); aArguments[0] >>= m_xXMLDocument; m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY ); m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY ); m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) ); m_pCurrentBufferNode = m_pRootBufferNode.get(); } OUString SAXEventKeeperImpl_getImplementationName () { return IMPLEMENTATION_NAME; } css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( ) { css::uno::Sequence aRet { "com.sun.star.xml.crypto.sax.SAXEventKeeper" }; return aRet; } /* XServiceInfo */ OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( ) { return SAXEventKeeperImpl_getImplementationName(); } sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName ) { return cppu::supportsService(this, rServiceName); } css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( ) { return SAXEventKeeperImpl_getSupportedServiceNames(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */