summaryrefslogtreecommitdiffstats
path: root/xmlsecurity/source/framework
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /xmlsecurity/source/framework
parentInitial commit. (diff)
downloadlibreoffice-cb75148ebd0135178ff46f89a30139c44f8d2040.tar.xz
libreoffice-cb75148ebd0135178ff46f89a30139c44f8d2040.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmlsecurity/source/framework')
-rw-r--r--xmlsecurity/source/framework/buffernode.cxx886
-rw-r--r--xmlsecurity/source/framework/buffernode.hxx119
-rw-r--r--xmlsecurity/source/framework/elementcollector.cxx137
-rw-r--r--xmlsecurity/source/framework/elementcollector.hxx80
-rw-r--r--xmlsecurity/source/framework/elementmark.cxx64
-rw-r--r--xmlsecurity/source/framework/elementmark.hxx67
-rw-r--r--xmlsecurity/source/framework/saxeventkeeperimpl.cxx1152
-rw-r--r--xmlsecurity/source/framework/securityengine.cxx67
-rw-r--r--xmlsecurity/source/framework/signaturecreatorimpl.cxx175
-rw-r--r--xmlsecurity/source/framework/signatureengine.cxx197
-rw-r--r--xmlsecurity/source/framework/signatureverifierimpl.cxx130
-rw-r--r--xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx113
12 files changed, 3187 insertions, 0 deletions
diff --git a/xmlsecurity/source/framework/buffernode.cxx b/xmlsecurity/source/framework/buffernode.cxx
new file mode 100644
index 000000000..cc6c37c18
--- /dev/null
+++ b/xmlsecurity/source/framework/buffernode.cxx
@@ -0,0 +1,886 @@
+/* -*- 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 "elementmark.hxx"
+#include "elementcollector.hxx"
+#include "buffernode.hxx"
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+
+BufferNode::BufferNode( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement )
+ :m_pParent(nullptr),
+ m_pBlocker(nullptr),
+ m_bAllReceived(false),
+ m_xXMLElement(xXMLElement)
+{
+}
+
+bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isECOfBeforeModifyIncluded ********************************
+ *
+ * NAME
+ * isECOfBeforeModifyIncluded -- checks whether there is some
+ * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority.
+ *
+ * SYNOPSIS
+ * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each ElementCollector on this BufferNode, if all following
+ * conditions are satisfied, then returns true:
+ * 1. the ElementCollector's priority is BEFOREMODIFY;
+ * 2. the ElementCollector's securityId can't be ignored.
+ * otherwise, returns false.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise
+ ******************************************************************************/
+{
+ return std::any_of(m_vElementCollectors.cbegin(), m_vElementCollectors.cend(),
+ [nIgnoredSecurityId](const ElementCollector* pElementCollector) {
+ return (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID ||
+ pElementCollector->getSecurityId() != nIgnoredSecurityId) &&
+ (pElementCollector->getPriority() == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY);
+ });
+}
+
+void BufferNode::setReceivedAll()
+/****** BufferNode/setReceiveAll *********************************************
+ *
+ * NAME
+ * setReceivedAll -- indicates that the element in this BufferNode has
+ * been completely buffered.
+ *
+ * SYNOPSIS
+ * setReceivedAll();
+ *
+ * FUNCTION
+ * sets the all-received flag and launches ElementCollector's notify
+ * process.
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ m_bAllReceived = true;
+ elementCollectorNotify();
+}
+
+
+void BufferNode::addElementCollector(const ElementCollector* pElementCollector)
+/****** BufferNode/addElementCollector ***************************************
+ *
+ * NAME
+ * addElementCollector -- adds a new ElementCollector to this BufferNode.
+ *
+ * SYNOPSIS
+ * addElementCollector(pElementCollector);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pElementCollector - the ElementCollector to be added
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ m_vElementCollectors.push_back( pElementCollector );
+ const_cast<ElementCollector*>(pElementCollector)->setBufferNode(this);
+}
+
+void BufferNode::removeElementCollector(const ElementCollector* pElementCollector)
+/****** BufferNode/removeElementCollector ************************************
+ *
+ * NAME
+ * removeElementCollector -- removes an ElementCollector from this
+ * BufferNode.
+ *
+ * SYNOPSIS
+ * removeElementCollector(pElementCollector);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pElementCollector - the ElementCollector to be removed
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ auto ii = std::find(m_vElementCollectors.begin(), m_vElementCollectors.end(), pElementCollector);
+ if (ii != m_vElementCollectors.end())
+ {
+ m_vElementCollectors.erase( ii );
+ const_cast<ElementCollector*>(pElementCollector)->setBufferNode(nullptr);
+ }
+}
+
+
+void BufferNode::setBlocker(const ElementMark* pBlocker)
+/****** BufferNode/setBlocker ************************************************
+ *
+ * NAME
+ * setBlocker -- adds a blocker to this BufferNode.
+ *
+ * SYNOPSIS
+ * setBlocker(pBlocker);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pBlocker - the new blocker to be attached
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * Because there is only one blocker permitted for a BufferNode, so the
+ * old blocker on this BufferNode, if there is one, will be overcasted.
+ ******************************************************************************/
+{
+ OSL_ASSERT(!(m_pBlocker != nullptr && pBlocker != nullptr));
+
+ m_pBlocker = const_cast<ElementMark*>(pBlocker);
+ if (m_pBlocker != nullptr)
+ {
+ m_pBlocker->setBufferNode(this);
+ }
+}
+
+OUString BufferNode::printChildren() const
+/****** BufferNode/printChildren *********************************************
+ *
+ * NAME
+ * printChildren -- prints children information into a string.
+ *
+ * SYNOPSIS
+ * result = printChildren();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * result - the information string
+ ******************************************************************************/
+{
+ OUStringBuffer rc;
+
+ for( const ElementCollector* ii : m_vElementCollectors )
+ {
+ rc.append("BufID=" + OUString::number(ii->getBufferId()));
+
+ if (ii->getModify())
+ {
+ rc.append("[M]");
+ }
+
+ rc.append(",Pri=");
+
+ switch (ii->getPriority())
+ {
+ case css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY:
+ rc.append("BEFOREMODIFY");
+ break;
+ case css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY:
+ rc.append("AFTERMODIFY");
+ break;
+ default:
+ rc.append("UNKNOWN");
+ break;
+ }
+
+ rc.append("(SecID=" + OUString::number(ii->getSecurityId()) + ") ");
+ }
+
+ return rc.makeStringAndClear();
+}
+
+bool BufferNode::hasAnything() const
+/****** BufferNode/hasAnything ***********************************************
+ *
+ * NAME
+ * hasAnything -- checks whether there is any ElementCollector or blocker
+ * on this BufferNode.
+ *
+ * SYNOPSIS
+ * bExist = hasAnything();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * bExist - true if there is, false otherwise.
+ ******************************************************************************/
+{
+ return (m_pBlocker || !m_vElementCollectors.empty());
+}
+
+bool BufferNode::hasChildren() const
+/****** BufferNode/hasChildren ***********************************************
+ *
+ * NAME
+ * hasChildren -- checks whether this BufferNode has any child
+ * BufferNode.
+ *
+ * SYNOPSIS
+ * bExist = hasChildren();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * bExist - true if there is, false otherwise.
+ ******************************************************************************/
+{
+ return (!m_vChildren.empty());
+}
+
+std::vector< std::unique_ptr<BufferNode> > const & BufferNode::getChildren() const
+{
+ return m_vChildren;
+}
+
+std::vector< std::unique_ptr<BufferNode> > BufferNode::releaseChildren()
+{
+ return std::move(m_vChildren);
+}
+
+const BufferNode* BufferNode::getFirstChild() const
+/****** BufferNode/getFirstChild *********************************************
+ *
+ * NAME
+ * getFirstChild -- retrieves the first child BufferNode.
+ *
+ * SYNOPSIS
+ * child = getFirstChild();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * child - the first child BufferNode, or NULL if there is no child
+ * BufferNode.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+
+ if (!m_vChildren.empty())
+ {
+ rc = m_vChildren.front().get();
+ }
+
+ return rc;
+}
+
+void BufferNode::addChild(std::unique_ptr<BufferNode> pChild, sal_Int32 nPosition)
+/****** BufferNode/addChild(pChild,nPosition) ********************************
+ *
+ * NAME
+ * addChild -- inserts a child BufferNode at specific position.
+ *
+ * SYNOPSIS
+ * addChild(pChild, nPosition);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode to be added.
+ * nPosition - the position where the new child locates.
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * If the nPosition is -1, then the new child BufferNode is appended
+ * at the end.
+ ******************************************************************************/
+{
+ if (nPosition == -1)
+ {
+ m_vChildren.push_back( std::move(pChild) );
+ }
+ else
+ {
+ m_vChildren.insert(m_vChildren.begin() + nPosition, std::move(pChild));
+ }
+}
+
+void BufferNode::addChild(std::unique_ptr<BufferNode> pChild)
+/****** BufferNode/addChild() ************************************************
+ *
+ * NAME
+ * addChild -- add a new child BufferNode.
+ *
+ * SYNOPSIS
+ * addChild(pChild);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode to be added.
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * The new child BufferNode is appended at the end.
+ ******************************************************************************/
+{
+ addChild(std::move(pChild), -1);
+}
+
+void BufferNode::removeChild(const BufferNode* pChild)
+/****** BufferNode/removeChild ***********************************************
+ *
+ * NAME
+ * removeChild -- removes and deletes a child BufferNode from the children list.
+ *
+ * SYNOPSIS
+ * removeChild(pChild);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode to be removed
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ auto ii = std::find_if(m_vChildren.begin(), m_vChildren.end(),
+ [pChild] (const std::unique_ptr<BufferNode>& i)
+ { return i.get() == pChild; });
+ if (ii != m_vChildren.end())
+ m_vChildren.erase( ii );
+}
+
+sal_Int32 BufferNode::indexOfChild(const BufferNode* pChild) const
+/****** BufferNode/indexOfChild **********************************************
+ *
+ * NAME
+ * indexOfChild -- gets the index of a child BufferNode.
+ *
+ * SYNOPSIS
+ * index = indexOfChild(pChild);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode whose index to be gotten
+ *
+ * RESULT
+ * index - the index of that child BufferNode. If that child BufferNode
+ * is not found, -1 is returned.
+ ******************************************************************************/
+{
+ auto ii = std::find_if(m_vChildren.begin(), m_vChildren.end(),
+ [pChild] (const std::unique_ptr<BufferNode>& i)
+ { return i.get() == pChild; });
+ if (ii == m_vChildren.end())
+ return -1;
+
+ return std::distance(m_vChildren.begin(), ii);
+}
+
+
+void BufferNode::setParent(const BufferNode* pParent)
+{
+ m_pParent = const_cast<BufferNode*>(pParent);
+}
+
+const BufferNode* BufferNode::getNextSibling() const
+/****** BufferNode/getNextSibling ********************************************
+ *
+ * NAME
+ * getNextSibling -- retrieves the next sibling BufferNode.
+ *
+ * SYNOPSIS
+ * sibling = getNextSibling();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * sibling - the next sibling BufferNode, or NULL if there is none.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+
+ if (m_pParent != nullptr)
+ {
+ rc = const_cast<BufferNode*>(m_pParent->getNextChild(this));
+ }
+
+ return rc;
+}
+
+const BufferNode* BufferNode::isAncestor(const BufferNode* pDescendant) const
+/****** BufferNode/isAncestor ************************************************
+ *
+ * NAME
+ * isAncestor -- checks whether this BufferNode is an ancestor of another
+ * BufferNode.
+ *
+ * SYNOPSIS
+ * bIs = isAncestor(pDescendant);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pDescendant - the BufferNode to be checked as a descendant
+ *
+ * RESULT
+ * bIs - true if this BufferNode is an ancestor of the pDescendant,
+ * false otherwise.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+
+ if (pDescendant != nullptr)
+ {
+ auto ii = std::find_if(m_vChildren.cbegin(), m_vChildren.cend(),
+ [&pDescendant](const std::unique_ptr<BufferNode>& pChild) {
+ return (pChild.get() == pDescendant) || (pChild->isAncestor(pDescendant) != nullptr);
+ });
+
+ if (ii != m_vChildren.end())
+ rc = ii->get();
+ }
+
+ return rc;
+}
+
+bool BufferNode::isPrevious(const BufferNode* pFollowing) const
+/****** BufferNode/isPrevious ************************************************
+ *
+ * NAME
+ * isPrevious -- checks whether this BufferNode is ahead of another
+ * BufferNode in the tree order.
+ *
+ * SYNOPSIS
+ * bIs = isPrevious(pFollowing);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pFollowing - the BufferNode to be checked as a following
+ *
+ * RESULT
+ * bIs - true if this BufferNode is ahead in the tree order, false
+ * otherwise.
+ ******************************************************************************/
+{
+ bool rc = false;
+
+ BufferNode* pNextBufferNode = const_cast<BufferNode*>(getNextNodeByTreeOrder());
+ while (pNextBufferNode != nullptr)
+ {
+ if (pNextBufferNode == pFollowing)
+ {
+ rc = true;
+ break;
+ }
+
+ pNextBufferNode = const_cast<BufferNode*>(pNextBufferNode->getNextNodeByTreeOrder());
+ }
+
+ return rc;
+}
+
+const BufferNode* BufferNode::getNextNodeByTreeOrder() const
+/****** BufferNode/getNextNodeByTreeOrder ************************************
+ *
+ * NAME
+ * getNextNodeByTreeOrder -- retrieves the next BufferNode in the tree
+ * order.
+ *
+ * SYNOPSIS
+ * next = getNextNodeByTreeOrder();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * next - the BufferNode following this BufferNode in the tree order,
+ * or NULL if there is none.
+ *
+ * NOTES
+ * The "next" node in tree order is defined as:
+ * 1. If a node has children, then the first child is;
+ * 2. otherwise, if it has a following sibling, then this sibling node is;
+ * 3. otherwise, if it has a parent node, the parent's next sibling
+ * node is;
+ * 4. otherwise, no "next" node exists.
+ ******************************************************************************/
+{
+ /*
+ * If this buffer node has m_vChildren, then return the first
+ * child.
+ */
+ if (hasChildren())
+ {
+ return getFirstChild();
+ }
+
+ /*
+ * Otherwise, it this buffer node has a following sibling,
+ * then return that sibling.
+ */
+ BufferNode* pNextSibling = const_cast<BufferNode*>(getNextSibling());
+ if (pNextSibling != nullptr)
+ {
+ return pNextSibling;
+ }
+
+ /*
+ * Otherwise, it this buffer node has parent, then return
+ * its parent's following sibling.
+ */
+ BufferNode* pNode = const_cast<BufferNode*>(this);
+ BufferNode* pParent;
+ BufferNode* pNextSiblingParent = nullptr;
+
+ do
+ {
+ if (pNode == nullptr)
+ {
+ break;
+ }
+
+ pParent = const_cast<BufferNode*>(pNode->getParent());
+ if (pParent != nullptr)
+ {
+ pNextSiblingParent = const_cast<BufferNode*>(pParent->getNextSibling());
+ }
+ pNode = pParent;
+
+ } while (pNextSiblingParent == nullptr);
+
+ return pNextSiblingParent;
+}
+
+
+void BufferNode::setXMLElement( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement )
+{
+ m_xXMLElement = xXMLElement;
+}
+
+void BufferNode::notifyBranch()
+/****** BufferNode/notifyBranch **********************************************
+ *
+ * NAME
+ * notifyBranch -- notifies each BufferNode in the branch of this
+ * BufferNode in the tree order.
+ *
+ * SYNOPSIS
+ * notifyBranch();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ for( std::unique_ptr<BufferNode>& pBufferNode : m_vChildren )
+ {
+ pBufferNode->elementCollectorNotify();
+ pBufferNode->notifyBranch();
+ }
+}
+
+void BufferNode::elementCollectorNotify()
+/****** BufferNode/elementCollectorNotify ************************************
+ *
+ * NAME
+ * elementCollectorNotify -- notifies this BufferNode.
+ *
+ * SYNOPSIS
+ * elementCollectorNotify();
+ *
+ * FUNCTION
+ * Notifies this BufferNode if the notification is not suppressed.
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * child - the first child BufferNode, or NULL if there is no child
+ * BufferNode.
+ ******************************************************************************/
+{
+ if (m_vElementCollectors.empty())
+ return;
+
+ css::xml::crypto::sax::ElementMarkPriority nMaxPriority = css::xml::crypto::sax::ElementMarkPriority_MINIMUM;
+ css::xml::crypto::sax::ElementMarkPriority nPriority;
+
+ /*
+ * get the max priority among ElementCollectors on this BufferNode
+ */
+ for( const ElementCollector* pElementCollector : m_vElementCollectors )
+ {
+ nPriority = pElementCollector->getPriority();
+ if (nPriority > nMaxPriority)
+ {
+ nMaxPriority = nPriority;
+ }
+ }
+
+ std::vector< const ElementCollector* > vElementCollectors( m_vElementCollectors );
+
+ for( const ElementCollector* ii : vElementCollectors )
+ {
+ ElementCollector* pElementCollector = const_cast<ElementCollector*>(ii);
+ nPriority = pElementCollector->getPriority();
+ bool bToModify = pElementCollector->getModify();
+
+ /*
+ * Only ElementCollector with the max priority can
+ * perform notify operation.
+ * Moreover, if any blocker exists in the subtree of
+ * this BufferNode, this ElementCollector can't do notify
+ * unless its priority is BEFOREMODIFY.
+ */
+ if (nPriority == nMaxPriority &&
+ (nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY ||
+ !isBlockerInSubTreeIncluded(pElementCollector->getSecurityId())))
+ {
+ /*
+ * If this ElementCollector will modify the buffered element, then
+ * special attention must be paid.
+ *
+ * If there is any ElementCollector in the subtree or any ancestor
+ * ElementCollector with PRI_BEFPREMODIFY priority, this
+ * ElementCollector can't perform notify operation, otherwise, it
+ * will destroy the buffered element, in turn, ElementCollectors
+ * mentioned above can't perform their mission.
+ */
+ //if (!(nMaxPriority == css::xml::crypto::sax::ElementMarkPriority_PRI_MODIFY &&
+ if (!(bToModify &&
+ (isECInSubTreeIncluded(pElementCollector->getSecurityId()) ||
+ isECOfBeforeModifyInAncestorIncluded(pElementCollector->getSecurityId()))
+ ))
+ {
+ pElementCollector->notifyListener();
+ }
+ }
+ }
+}
+
+bool BufferNode::isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isECInSubTreeIncluded *************************************
+ *
+ * NAME
+ * isECInSubTreeIncluded -- checks whether there is any ElementCollector
+ * in the branch of this BufferNode.
+ *
+ * SYNOPSIS
+ * bExist = isECInSubTreeIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each BufferNode in the branch of this BufferNode, if there is
+ * an ElementCollector whose signatureId is not ignored, then return
+ * true, otherwise, false returned.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise.
+ ******************************************************************************/
+{
+ bool rc = std::any_of(m_vElementCollectors.begin(), m_vElementCollectors.end(),
+ [nIgnoredSecurityId](const ElementCollector* pElementCollector) {
+ return nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID ||
+ pElementCollector->getSecurityId() != nIgnoredSecurityId;
+ });
+
+ if ( !rc )
+ {
+ rc = std::any_of(m_vChildren.begin(), m_vChildren.end(),
+ [nIgnoredSecurityId](const std::unique_ptr<BufferNode>& pBufferNode) {
+ return pBufferNode->isECInSubTreeIncluded(nIgnoredSecurityId);
+ });
+ }
+
+ return rc;
+}
+
+bool BufferNode::isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isECOfBeforeModifyInAncestorIncluded **********************
+ *
+ * NAME
+ * isECOfBeforeModifyInAncestorIncluded -- checks whether there is some
+ * ancestor BufferNode which has ElementCollector with PRI_BEFPREMODIFY
+ * priority.
+ *
+ * SYNOPSIS
+ * bExist = isECOfBeforeModifyInAncestorIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each ancestor BufferNode through the parent link, if there is
+ * an ElementCollector with PRI_BEFPREMODIFY priority and its
+ * signatureId is not ignored, then return true, otherwise, false
+ * returned.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise.
+ ******************************************************************************/
+{
+ bool rc = false;
+
+ BufferNode* pParentNode = m_pParent;
+ while (pParentNode != nullptr)
+ {
+ if (pParentNode->isECOfBeforeModifyIncluded(nIgnoredSecurityId))
+ {
+ rc = true;
+ break;
+ }
+
+ pParentNode = const_cast<BufferNode*>(pParentNode->getParent());
+ }
+
+ return rc;
+}
+
+bool BufferNode::isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isBlockerInSubTreeIncluded ********************************
+ *
+ * NAME
+ * isBlockerInSubTreeIncluded -- checks whether there is some BufferNode
+ * which has blocker on it
+ *
+ * SYNOPSIS
+ * bExist = isBlockerInSubTreeIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each BufferNode in the branch of this BufferNode, if one has
+ * a blocker on it, and the blocker's securityId is not ignored, then
+ * returns true; otherwise, false returns.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise.
+ ******************************************************************************/
+{
+ return std::any_of(m_vChildren.begin(), m_vChildren.end(),
+ [nIgnoredSecurityId](const std::unique_ptr<BufferNode>& pBufferNode) {
+ ElementMark* pBlocker = pBufferNode->getBlocker();
+ return (pBlocker != nullptr &&
+ (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID ||
+ pBlocker->getSecurityId() != nIgnoredSecurityId )) ||
+ pBufferNode->isBlockerInSubTreeIncluded(nIgnoredSecurityId);
+ });
+}
+
+const BufferNode* BufferNode::getNextChild(const BufferNode* pChild) const
+/****** BufferNode/getNextChild **********************************************
+ *
+ * NAME
+ * getNextChild -- get the next child BufferNode.
+ *
+ * SYNOPSIS
+ * nextChild = getNextChild();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode whose next node is retrieved.
+ *
+ * RESULT
+ * nextChild - the next child BufferNode after the pChild, or NULL if
+ * there is none.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+ bool bChildFound = false;
+
+ for( std::unique_ptr<BufferNode> const & i : m_vChildren )
+ {
+ if (bChildFound)
+ {
+ rc = i.get();
+ break;
+ }
+
+ if( i.get() == pChild )
+ {
+ bChildFound = true;
+ }
+ }
+
+ return rc;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/buffernode.hxx b/xmlsecurity/source/framework/buffernode.hxx
new file mode 100644
index 000000000..0202195de
--- /dev/null
+++ b/xmlsecurity/source/framework/buffernode.hxx
@@ -0,0 +1,119 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace com::sun::star::xml::wrapper
+{
+class XXMLElementWrapper;
+}
+
+class ElementMark;
+class ElementCollector;
+
+class BufferNode final
+/****** buffernode.hxx/CLASS BufferNode ***************************************
+ *
+ * NAME
+ * BufferNode -- Class to maintain the tree of buffered elements
+ *
+ * FUNCTION
+ * One BufferNode object represents a buffered element in the document
+ * wrapper component.
+ * All BufferNode objects construct a tree which has the same structure
+ * of all buffered elements. That is to say, if one buffered element is
+ * an ancestor of another buffered element, then the corresponding
+ * BufferNode objects are also in ancestor/descendant relationship.
+ * This class is used to manipulate the tree of buffered elements.
+ ******************************************************************************/
+{
+private:
+ /* the parent BufferNode */
+ BufferNode* m_pParent;
+
+ /* all child BufferNodes */
+ std::vector<std::unique_ptr<BufferNode>> m_vChildren;
+
+ /* all ElementCollector holding this BufferNode */
+ std::vector<const ElementCollector*> m_vElementCollectors;
+
+ /*
+ * the blocker holding this BufferNode, one BufferNode can have one
+ * blocker at most
+ */
+ ElementMark* m_pBlocker;
+
+ /*
+ * whether the element has completely buffered by the document wrapper
+ * component
+ */
+ bool m_bAllReceived;
+
+ /* the XMLElementWrapper of the buffered element */
+ css::uno::Reference<css::xml::wrapper::XXMLElementWrapper> m_xXMLElement;
+
+private:
+ bool isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const;
+ bool isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const;
+ bool isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const;
+ const BufferNode* getNextChild(const BufferNode* pChild) const;
+
+public:
+ explicit BufferNode(
+ const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& xXMLElement);
+
+ bool isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const;
+ void setReceivedAll();
+ bool isAllReceived() const { return m_bAllReceived; }
+ void addElementCollector(const ElementCollector* pElementCollector);
+ void removeElementCollector(const ElementCollector* pElementCollector);
+ ElementMark* getBlocker() const { return m_pBlocker; }
+ void setBlocker(const ElementMark* pBlocker);
+ OUString printChildren() const;
+ bool hasAnything() const;
+ bool hasChildren() const;
+ std::vector<std::unique_ptr<BufferNode>> const& getChildren() const;
+ std::vector<std::unique_ptr<BufferNode>> releaseChildren();
+ const BufferNode* getFirstChild() const;
+ void addChild(std::unique_ptr<BufferNode> pChild, sal_Int32 nPosition);
+ void addChild(std::unique_ptr<BufferNode> pChild);
+ void removeChild(const BufferNode* pChild);
+ sal_Int32 indexOfChild(const BufferNode* pChild) const;
+ const BufferNode* getParent() const { return m_pParent; }
+ void setParent(const BufferNode* pParent);
+ const BufferNode* getNextSibling() const;
+ const BufferNode* isAncestor(const BufferNode* pDescendant) const;
+ bool isPrevious(const BufferNode* pFollowing) const;
+ const BufferNode* getNextNodeByTreeOrder() const;
+ const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& getXMLElement() const
+ {
+ return m_xXMLElement;
+ }
+ void
+ setXMLElement(const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& xXMLElement);
+ void notifyBranch();
+ void elementCollectorNotify();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementcollector.cxx b/xmlsecurity/source/framework/elementcollector.cxx
new file mode 100644
index 000000000..7801d6328
--- /dev/null
+++ b/xmlsecurity/source/framework/elementcollector.cxx
@@ -0,0 +1,137 @@
+/* -*- 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 "elementmark.hxx"
+#include "elementcollector.hxx"
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp>
+
+ElementCollector::ElementCollector(
+ sal_Int32 nBufferId,
+ css::xml::crypto::sax::ElementMarkPriority nPriority,
+ bool bToModify,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
+ :ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nBufferId),
+ m_nPriority(nPriority),
+ m_bToModify(bToModify),
+ m_bAbleToNotify(false),
+ m_bNotified(false),
+ m_xReferenceResolvedListener(xReferenceResolvedListener)
+/****** ElementCollector/ElementCollector *************************************
+ *
+ * NAME
+ * ElementCollector -- constructor method
+ *
+ * SYNOPSIS
+ * ElementCollector(nSecurityId, nBufferId, nPriority, bToModify
+ * xReferenceResolvedListener);
+ *
+ * FUNCTION
+ * construct an ElementCollector object.
+ *
+ * INPUTS
+ * nSecurityId - represents which security entity the buffer node is
+ * related with. Either a signature or an encryption is
+ * a security entity.
+ * nBufferId - the id of the element buffered in the document
+ * wrapper component. The document wrapper component
+ * uses this id to search the particular buffered
+ * element.
+ * nPriority - the priority value. ElementCollector with lower
+ * priority value can't notify until all ElementCollectors
+ * with higher priority value have notified.
+ * bToModify - A flag representing whether this ElementCollector
+ * notification will cause the modification of its working
+ * element.
+ * xReferenceResolvedListener
+ * - the listener that this ElementCollector notifies to.
+ ******************************************************************************/
+{
+ m_type = css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR;
+}
+
+
+void ElementCollector::notifyListener()
+/****** ElementCollector/notifyListener ***************************************
+ *
+ * NAME
+ * notifyListener -- enable the ability to notify the listener
+ *
+ * SYNOPSIS
+ * notifyListener();
+ *
+ * FUNCTION
+ * enable the ability to notify the listener and try to notify then.
+ ******************************************************************************/
+{
+ m_bAbleToNotify = true;
+ doNotify();
+}
+
+void ElementCollector::setReferenceResolvedListener(
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
+/****** ElementCollector/setReferenceResolvedListener *************************
+ *
+ * NAME
+ * setReferenceResolvedListener -- configures a listener for the buffer
+ * node in this object
+ *
+ * SYNOPSIS
+ * setReferenceResolvedListener(xReferenceResolvedListener);
+ *
+ * FUNCTION
+ * configures a new listener and try to notify then.
+ *
+ * INPUTS
+ * xReferenceResolvedListener - the new listener
+ ******************************************************************************/
+{
+ m_xReferenceResolvedListener = xReferenceResolvedListener;
+ doNotify();
+}
+
+void ElementCollector::doNotify()
+/****** ElementCollector/doNotify *********************************************
+ *
+ * NAME
+ * doNotify -- tries to notify the listener
+ *
+ * SYNOPSIS
+ * doNotify();
+ *
+ * FUNCTION
+ * notifies the listener when all below conditions are satisfied:
+ * the listener has not been notified;
+ * the notify right is granted;
+ * the listener has already been configured;
+ * the security id has already been configure
+ ******************************************************************************/
+{
+ if (!m_bNotified &&
+ m_bAbleToNotify &&
+ m_xReferenceResolvedListener.is() &&
+ m_nSecurityId != css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID)
+ {
+ m_bNotified = true;
+ m_xReferenceResolvedListener->referenceResolved(m_nBufferId);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementcollector.hxx b/xmlsecurity/source/framework/elementcollector.hxx
new file mode 100644
index 000000000..0f797572a
--- /dev/null
+++ b/xmlsecurity/source/framework/elementcollector.hxx
@@ -0,0 +1,80 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "elementmark.hxx"
+#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace com::sun::star::xml::crypto::sax { class XReferenceResolvedListener; }
+
+class ElementCollector : public ElementMark
+/****** elementcollector.hxx/CLASS ElementCollector ***************************
+ *
+ * NAME
+ * ElementCollector -- Class to manipulate an element collector
+ *
+ * FUNCTION
+ * This class is derived from the ElementMark class. Beyond the function
+ * of the ElementMark class, this class also maintains the priority, and
+ * manages the notify process
+ ******************************************************************************/
+{
+private:
+ /*
+ * the notify priority, is one of following values:
+ * AFTERMODIFY - this ElementCollector will notify after all
+ * internal modifications have finished.
+ * BEFOREMODIFY - this ElementCollector must notify before any
+ * internal modification happens.
+ */
+ css::xml::crypto::sax::ElementMarkPriority const m_nPriority;
+
+ /*
+ * the modify flag, representing whether which elementcollector will
+ * modify its data.
+ */
+ bool const m_bToModify;
+
+ /* the notify enable flag, see notifyListener method */
+ bool m_bAbleToNotify;
+
+ /* whether the listener has been notified */
+ bool m_bNotified;
+
+ /* the listener to be notified */
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > m_xReferenceResolvedListener;
+
+public:
+ ElementCollector(
+ sal_Int32 nBufferId,
+ css::xml::crypto::sax::ElementMarkPriority nPriority,
+ bool bToModify,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener);
+
+ css::xml::crypto::sax::ElementMarkPriority getPriority() const { return m_nPriority;}
+ bool getModify() const { return m_bToModify;}
+ void notifyListener();
+ void setReferenceResolvedListener(
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& referenceResolvedListener);
+ void doNotify();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementmark.cxx b/xmlsecurity/source/framework/elementmark.cxx
new file mode 100644
index 000000000..71444d7cd
--- /dev/null
+++ b/xmlsecurity/source/framework/elementmark.cxx
@@ -0,0 +1,64 @@
+/* -*- 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 "elementmark.hxx"
+
+ElementMark::ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId)
+ :m_pBufferNode(nullptr),
+ m_nSecurityId(nSecurityId),
+ m_nBufferId(nBufferId),
+ m_type(css::xml::crypto::sax::ElementMarkType_ELEMENTMARK)
+/****** ElementMark/ElementMark ***********************************************
+ *
+ * NAME
+ * ElementMark -- constructor method
+ *
+ * SYNOPSIS
+ * ElementMark(nSecurityId, nBufferId);
+ *
+ * FUNCTION
+ * construct an ElementMark object.
+ *
+ * INPUTS
+ * nSecurityId - represents which security entity the buffer node is
+ * related with. Either a signature or an encryption is
+ * a security entity.
+ * nBufferId - the id of the element buffered in the document
+ * wrapper component. The document wrapper component
+ * uses this id to search the particular buffered
+ * element.
+ ******************************************************************************/
+{
+}
+
+
+void ElementMark::setBufferNode(const BufferNode* pBufferNode)
+{
+ m_pBufferNode = const_cast<BufferNode*>(pBufferNode);
+}
+
+
+void ElementMark::setSecurityId(sal_Int32 nSecurityId)
+{
+ m_nSecurityId = nSecurityId;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementmark.hxx b/xmlsecurity/source/framework/elementmark.hxx
new file mode 100644
index 000000000..94ca71fdf
--- /dev/null
+++ b/xmlsecurity/source/framework/elementmark.hxx
@@ -0,0 +1,67 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/ElementMarkType.hpp>
+
+class BufferNode;
+
+class ElementMark
+/****** elementmark.hxx/CLASS ElementMark *************************************
+ *
+ * NAME
+ * ElementMark -- Class to manipulate an element mark
+ *
+ * FUNCTION
+ * This class maintains the security id, buffer id and its type for a
+ * buffer node.
+ ******************************************************************************/
+{
+protected:
+ /* the BufferNode maintained by this object */
+ BufferNode* m_pBufferNode;
+
+ /* the security Id */
+ sal_Int32 m_nSecurityId;
+
+ /* the buffer Id */
+ sal_Int32 const m_nBufferId;
+
+ /*
+ * the type value, is one of following values:
+ * TYPEOFELEMENTMARK - the default value, represents a blocker if
+ * not changed
+ * TYPEOFELEMENTCOLLECTOR - represents an ElementCollector
+ */
+ css::xml::crypto::sax::ElementMarkType m_type;
+
+public:
+ ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId);
+ virtual ~ElementMark(){};
+
+ BufferNode* getBufferNode() const { return m_pBufferNode; }
+ void setBufferNode(const BufferNode* pBufferNode);
+ sal_Int32 getSecurityId() const { return m_nSecurityId; }
+ void setSecurityId(sal_Int32 nSecurityId);
+ css::xml::crypto::sax::ElementMarkType getType() const { return m_type; }
+ sal_Int32 getBufferId() const { return m_nBufferId; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
new file mode 100644
index 000000000..b5a7f0272
--- /dev/null
+++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
@@ -0,0 +1,1152 @@
+/* -*- 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 <framework/saxeventkeeperimpl.hxx>
+#include "buffernode.hxx"
+#include "elementmark.hxx"
+#include "elementcollector.hxx"
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
+#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <algorithm>
+
+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<BufferNode>(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<ElementMark*>(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<const ElementMark>& 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; i<nIndent; ++i )
+ {
+ rc.append(" ");
+ }
+
+ if (pBufferNode == m_pCurrentBufferNode)
+ {
+ rc.append("[%]");
+ }
+
+ if (pBufferNode == m_pCurrentBlockingBufferNode)
+ {
+ rc.append("[B]");
+ }
+
+ rc.append(" " + m_xXMLDocument->getNodeName(pBufferNode->getXMLElement()));
+
+ BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
+ if (pParent != nullptr)
+ {
+ rc.append("[" + m_xXMLDocument->getNodeName(pParent->getXMLElement()) + "]");
+ }
+
+ rc.append(":EC=" + pBufferNode->printChildren() + " BR=");
+
+ ElementMark * pBlocker = pBufferNode->getBlocker();
+ if (pBlocker != nullptr)
+ {
+ rc.append( OUString::number(pBlocker->getBufferId()) +
+ "(SecId=" + OUString::number( pBlocker->getSecurityId() ) + ") ");
+ }
+ rc.append("\n");
+
+ std::vector< std::unique_ptr<BufferNode> > 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<BufferNode> > const & vChildren = pBufferNode->getChildren();
+
+ css::uno::Sequence < css::uno::Reference<
+ css::xml::wrapper::XXMLElementWrapper > > aChildrenCollection ( vChildren.size());
+
+ std::transform(vChildren.begin(), vChildren.end(), aChildrenCollection.getArray(),
+ [](const auto& i) { return i->getXMLElement(); });
+
+ 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<BufferNode*>(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<BufferNode> > 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<BufferNode*>(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<BufferNode*>(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<ElementCollector*>(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<const ElementMark>(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<const ElementMark>(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<ElementCollector*>(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);
+ auto aAttributesRange = asNonConstRange(aAttributes);
+
+ for ( int i = 0; i<nLength; ++i )
+ {
+ aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i));
+ aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(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<BufferNode*>(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 "com.sun.star.xml.security.framework.SAXEventKeeperImpl";
+}
+
+css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.sax.SAXEventKeeper" };
+}
+
+/* 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: */
diff --git a/xmlsecurity/source/framework/securityengine.cxx b/xmlsecurity/source/framework/securityengine.cxx
new file mode 100644
index 000000000..e276163d4
--- /dev/null
+++ b/xmlsecurity/source/framework/securityengine.cxx
@@ -0,0 +1,67 @@
+/* -*- 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 <framework/securityengine.hxx>
+
+
+SecurityEngine::SecurityEngine()
+ :m_nIdOfTemplateEC(-1),
+ m_nNumOfResolvedReferences(0),
+ m_nIdOfKeyEC(-1),
+ m_bMissionDone(false),
+ m_nSecurityId(-1),
+ m_nStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN)
+{
+}
+
+/* XReferenceResolvedListener */
+void SAL_CALL SecurityEngine::referenceResolved( sal_Int32 /*referenceId*/)
+{
+ m_nNumOfResolvedReferences++;
+ tryToPerform();
+}
+
+/* XKeyCollector */
+void SAL_CALL SecurityEngine::setKeyId( sal_Int32 id )
+{
+ m_nIdOfKeyEC = id;
+ tryToPerform();
+}
+
+/* XMissionTaker */
+sal_Bool SAL_CALL SecurityEngine::endMission( )
+{
+ bool rc = m_bMissionDone;
+
+ if (!rc)
+ {
+ clearUp( );
+
+ notifyResultListener();
+ m_bMissionDone = true;
+ }
+
+ m_xResultListener = nullptr;
+ m_xSAXEventKeeper = nullptr;
+
+ return rc;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/signaturecreatorimpl.cxx b/xmlsecurity/source/framework/signaturecreatorimpl.cxx
new file mode 100644
index 000000000..4371b7ae6
--- /dev/null
+++ b/xmlsecurity/source/framework/signaturecreatorimpl.cxx
@@ -0,0 +1,175 @@
+/* -*- 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 <framework/signaturecreatorimpl.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; }
+
+using namespace com::sun::star::uno;
+
+SignatureCreatorImpl::SignatureCreatorImpl()
+ : m_nIdOfBlocker(-1)
+{
+}
+
+SignatureCreatorImpl::~SignatureCreatorImpl( )
+{
+}
+
+void SignatureCreatorImpl::notifyResultListener() const
+/****** SignatureCreatorImpl/notifyResultListener *****************************
+ *
+ * NAME
+ * notifyResultListener -- notifies the listener about the signature
+ * creation result.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >
+ xSignatureCreationResultListener ( m_xResultListener , css::uno::UNO_QUERY ) ;
+
+ xSignatureCreationResultListener->signatureCreated( m_nSecurityId, m_nStatus );
+}
+
+void SignatureCreatorImpl::startEngine(const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate)
+/****** SignatureCreatorImpl/startEngine *************************************
+ *
+ * NAME
+ * startEngine -- generates the signature.
+ *
+ * FUNCTION
+ * generates the signature element, then if succeeds, updates the link
+ * of old template element to the new signature element in
+ * SAXEventKeeper.
+ *
+ * INPUTS
+ * xSignatureTemplate - the signature template (along with all referenced
+ * elements) to be signed.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > xResultTemplate;
+ try
+ {
+ xResultTemplate = m_xXMLSignature->generate(css::uno::Reference<css::xml::crypto::XXMLSignatureTemplate>(xSignatureTemplate), m_xSecurityEnvironment);
+ m_nStatus = xResultTemplate->getStatus();
+ }
+ catch( css::uno::Exception& )
+ {
+ m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED;
+ }
+
+ if (m_nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED)
+ {
+ css::uno::Reference < css::xml::wrapper::XXMLElementWrapper > xResultSignature = xResultTemplate->getTemplate();
+ m_xSAXEventKeeper->setElement(m_nIdOfTemplateEC, xResultSignature);
+ }
+}
+
+void SignatureCreatorImpl::clearUp() const
+/****** SignatureCreatorImpl/clearUp *****************************************
+ *
+ * NAME
+ * clearUp -- clear up all resources used by the signature generation.
+ *
+ * SYNOPSIS
+ * clearUp( );
+ *
+ * FUNCTION
+ * cleaning resources up includes:
+ * 1. SignatureEngine's clearing up;
+ * 2. releases the Blocker for the signature template element.
+ ******************************************************************************/
+{
+ SignatureEngine::clearUp();
+
+ if (m_nIdOfBlocker != -1)
+ {
+ m_xSAXEventKeeper->removeBlocker(m_nIdOfBlocker);
+ }
+}
+
+/* XBlockerMonitor */
+void SAL_CALL SignatureCreatorImpl::setBlockerId( sal_Int32 id )
+{
+ m_nIdOfBlocker = id;
+ tryToPerform();
+}
+
+/* XSignatureCreationResultBroadcaster */
+void SAL_CALL SignatureCreatorImpl::addSignatureCreationResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener )
+{
+ m_xResultListener = listener;
+ tryToPerform();
+}
+
+void SAL_CALL SignatureCreatorImpl::removeSignatureCreationResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >&)
+{
+}
+
+/* XInitialization */
+void SAL_CALL SignatureCreatorImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
+{
+ OSL_ASSERT(aArguments.getLength() == 5);
+
+ OUString ouTempString;
+
+ aArguments[0] >>= ouTempString;
+ m_nSecurityId = ouTempString.toInt32();
+ aArguments[1] >>= m_xSAXEventKeeper;
+ aArguments[2] >>= ouTempString;
+ m_nIdOfTemplateEC = ouTempString.toInt32();
+ aArguments[3] >>= m_xSecurityEnvironment;
+ aArguments[4] >>= m_xXMLSignature;
+}
+
+
+OUString SignatureCreatorImpl_getImplementationName ()
+{
+ return "com.sun.star.xml.security.framework.SignatureCreatorImpl";
+}
+
+css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.sax.SignatureCreator" };
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SignatureCreatorImpl::getImplementationName( )
+{
+ return SignatureCreatorImpl_getImplementationName();
+}
+
+sal_Bool SAL_CALL SignatureCreatorImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL SignatureCreatorImpl::getSupportedServiceNames( )
+{
+ return SignatureCreatorImpl_getSupportedServiceNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/signatureengine.cxx b/xmlsecurity/source/framework/signatureengine.cxx
new file mode 100644
index 000000000..0390ea7e6
--- /dev/null
+++ b/xmlsecurity/source/framework/signatureengine.cxx
@@ -0,0 +1,197 @@
+/* -*- 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 <framework/signatureengine.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; }
+
+using namespace com::sun::star::uno;
+
+SignatureEngine::SignatureEngine()
+ : m_nTotalReferenceNumber(-1)
+{
+}
+
+bool SignatureEngine::checkReady() const
+/****** SignatureEngine/checkReady *******************************************
+ *
+ * NAME
+ * checkReady -- checks the conditions for the main operation.
+ *
+ * SYNOPSIS
+ * bReady = checkReady( );
+ *
+ * FUNCTION
+ * checks whether all following conditions are satisfied:
+ * 1. the main operation has't begun yet;
+ * 2. the key material is known;
+ * 3. the amount of reference is known;
+ * 4. all of referenced elements, the key element and the signature
+ * template are buffered.
+ *
+ * RESULT
+ * bReady - true if all conditions are satisfied, false otherwise
+ ******************************************************************************/
+{
+ bool rc = true;
+
+ sal_Int32 nKeyInc = 0;
+ if (m_nIdOfKeyEC != 0)
+ {
+ nKeyInc = 1;
+ }
+
+ if (m_bMissionDone ||
+ m_nIdOfKeyEC == -1 ||
+ m_nTotalReferenceNumber == -1 ||
+ m_nTotalReferenceNumber+1+nKeyInc > m_nNumOfResolvedReferences)
+ {
+ rc = false;
+ }
+
+ return rc;
+}
+
+void SignatureEngine::tryToPerform( )
+/****** SignatureEngine/tryToPerform *****************************************
+ *
+ * NAME
+ * tryToPerform -- tries to perform the signature operation.
+ *
+ * FUNCTION
+ * if the situation is ready, perform following operations.
+ * 1. prepares a signature template;
+ * 2. calls the signature bridge component;
+ * 3. clears up all used resources;
+ * 4. notifies the result listener;
+ * 5. sets the "accomplishment" flag.
+ ******************************************************************************/
+{
+ if (!checkReady())
+ return;
+
+ rtl::Reference<XMLSignatureTemplateImpl> xSignatureTemplate = new XMLSignatureTemplateImpl();
+
+ css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >
+ xXMLElement = m_xSAXEventKeeper->getElement( m_nIdOfTemplateEC );
+
+ xSignatureTemplate->setTemplate(xXMLElement);
+
+ for( const auto i : m_vReferenceIds )
+ {
+ xXMLElement = m_xSAXEventKeeper->getElement( i );
+ xSignatureTemplate->setTarget(xXMLElement);
+ }
+
+ /*
+ * set the Uri binding
+ */
+ xSignatureTemplate->setBinding( this );
+
+ startEngine(xSignatureTemplate);
+
+ /*
+ * done
+ */
+ clearUp( );
+
+ notifyResultListener();
+
+ m_bMissionDone = true;
+}
+
+void SignatureEngine::clearUp( ) const
+/****** SignatureEngine/clearUp **********************************************
+ *
+ * NAME
+ * clearUp -- clear up all resources used by this operation.
+ *
+ * FUNCTION
+ * cleaning resources up includes:
+ * 1. releases the ElementCollector for the signature template element;
+ * 2. releases ElementCollectors for referenced elements;
+ * 3. releases the ElementCollector for the key element, if there is one.
+ ******************************************************************************/
+{
+ css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedBroadcaster >
+ xReferenceResolvedBroadcaster( m_xSAXEventKeeper, css::uno::UNO_QUERY );
+ xReferenceResolvedBroadcaster->removeReferenceResolvedListener(
+ m_nIdOfTemplateEC,
+ static_cast<const css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedListener > >(static_cast<SecurityEngine *>(const_cast<SignatureEngine *>(this))));
+
+ m_xSAXEventKeeper->removeElementCollector(m_nIdOfTemplateEC);
+
+ for( const auto& i : m_vReferenceIds )
+ {
+ xReferenceResolvedBroadcaster->removeReferenceResolvedListener(
+ i,
+ static_cast<const css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedListener > >(static_cast<SecurityEngine *>(const_cast<SignatureEngine *>(this))));
+ m_xSAXEventKeeper->removeElementCollector(i);
+ }
+
+ if (m_nIdOfKeyEC != 0 && m_nIdOfKeyEC != -1)
+ {
+ m_xSAXEventKeeper->removeElementCollector(m_nIdOfKeyEC);
+ }
+}
+
+/* XReferenceCollector */
+void SAL_CALL SignatureEngine::setReferenceCount( sal_Int32 count )
+{
+ m_nTotalReferenceNumber = count;
+ tryToPerform();
+}
+
+void SAL_CALL SignatureEngine::setReferenceId( sal_Int32 id )
+{
+ m_vReferenceIds.push_back( id );
+}
+
+/* XUriBinding */
+void SAL_CALL SignatureEngine::setUriBinding(
+ const OUString& uri,
+ const css::uno::Reference< css::io::XInputStream >& aInputStream )
+{
+ m_vUris.push_back(uri);
+ m_vXInputStreams.push_back(aInputStream);
+}
+
+css::uno::Reference< css::io::XInputStream > SAL_CALL SignatureEngine::getUriBinding( const OUString& uri )
+{
+ css::uno::Reference< css::io::XInputStream > xInputStream;
+
+ int size = m_vUris.size();
+
+ for( int i=0; i<size; ++i)
+ {
+ if (m_vUris[i] == uri)
+ {
+ xInputStream = m_vXInputStreams[i];
+ break;
+ }
+ }
+
+ return xInputStream;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/signatureverifierimpl.cxx b/xmlsecurity/source/framework/signatureverifierimpl.cxx
new file mode 100644
index 000000000..44e9e4c0a
--- /dev/null
+++ b/xmlsecurity/source/framework/signatureverifierimpl.cxx
@@ -0,0 +1,130 @@
+/* -*- 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 <framework/signatureverifierimpl.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+
+SignatureVerifierImpl::SignatureVerifierImpl()
+{
+}
+
+SignatureVerifierImpl::~SignatureVerifierImpl()
+{
+}
+
+void SignatureVerifierImpl::notifyResultListener() const
+/****** SignatureVerifierImpl/notifyResultListener ***************************
+ *
+ * NAME
+ * notifyResultListener -- notifies the listener about the verify result.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >
+ xSignatureVerifyResultListener ( m_xResultListener , css::uno::UNO_QUERY ) ;
+
+ xSignatureVerifyResultListener->signatureVerified( m_nSecurityId, m_nStatus );
+}
+
+void SignatureVerifierImpl::startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate)
+/****** SignatureVerifierImpl/startEngine ************************************
+ *
+ * NAME
+ * startEngine -- verifies the signature.
+ *
+ * INPUTS
+ * xSignatureTemplate - the signature template (along with all referenced
+ * elements) to be verified.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > xResultTemplate;
+ try
+ {
+ xResultTemplate = m_xXMLSignature->validate(css::uno::Reference<css::xml::crypto::XXMLSignatureTemplate>(xSignatureTemplate), m_xXMLSecurityContext);
+ m_nStatus = xResultTemplate->getStatus();
+ }
+ catch( css::uno::Exception& )
+ {
+ m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED;
+ }
+}
+
+/* XSignatureVerifyResultBroadcaster */
+void SAL_CALL SignatureVerifierImpl::addSignatureVerifyResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener )
+{
+ m_xResultListener = listener;
+ tryToPerform();
+}
+
+void SAL_CALL SignatureVerifierImpl::removeSignatureVerifyResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >&)
+{
+}
+
+/* XInitialization */
+void SAL_CALL SignatureVerifierImpl::initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments )
+{
+ OSL_ASSERT(aArguments.getLength() == 5);
+
+ OUString ouTempString;
+
+ aArguments[0] >>= ouTempString;
+ m_nSecurityId = ouTempString.toInt32();
+ aArguments[1] >>= m_xSAXEventKeeper;
+ aArguments[2] >>= ouTempString;
+ m_nIdOfTemplateEC = ouTempString.toInt32();
+ aArguments[3] >>= m_xXMLSecurityContext;
+ aArguments[4] >>= m_xXMLSignature;
+}
+
+
+OUString SignatureVerifierImpl_getImplementationName ()
+{
+ return "com.sun.star.xml.security.framework.SignatureVerifierImpl";
+}
+
+css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.sax.SignatureVerifier" };
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SignatureVerifierImpl::getImplementationName( )
+{
+ return SignatureVerifierImpl_getImplementationName();
+}
+
+sal_Bool SAL_CALL SignatureVerifierImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL SignatureVerifierImpl::getSupportedServiceNames( )
+{
+ return SignatureVerifierImpl_getSupportedServiceNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx
new file mode 100644
index 000000000..203f0fea2
--- /dev/null
+++ b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx
@@ -0,0 +1,113 @@
+/* -*- 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 <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star::uno ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+
+using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
+using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
+
+XMLSignatureTemplateImpl::XMLSignatureTemplateImpl()
+ :m_nStatus ( css::xml::crypto::SecurityOperationStatus_UNKNOWN )
+{
+}
+
+XMLSignatureTemplateImpl::~XMLSignatureTemplateImpl() {
+}
+
+/* XXMLSignatureTemplate */
+void SAL_CALL XMLSignatureTemplateImpl::setTemplate( const Reference< XXMLElementWrapper >& aTemplate )
+{
+ m_xTemplate = aTemplate ;
+}
+
+/* XXMLSignatureTemplate */
+Reference< XXMLElementWrapper > SAL_CALL XMLSignatureTemplateImpl::getTemplate()
+{
+ return m_xTemplate ;
+}
+
+void SAL_CALL XMLSignatureTemplateImpl::setTarget( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement )
+{
+ targets.push_back( aXmlElement );
+}
+
+css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAL_CALL XMLSignatureTemplateImpl::getTargets()
+{
+ return comphelper::containerToSequence(targets);
+}
+
+void SAL_CALL XMLSignatureTemplateImpl::setBinding(
+ const css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding )
+{
+ m_xUriBinding = aUriBinding;
+}
+
+css::uno::Reference< css::xml::crypto::XUriBinding > SAL_CALL XMLSignatureTemplateImpl::getBinding()
+{
+ return m_xUriBinding;
+}
+
+void SAL_CALL XMLSignatureTemplateImpl::setStatus(
+ css::xml::crypto::SecurityOperationStatus status )
+{
+ m_nStatus = status;
+}
+
+css::xml::crypto::SecurityOperationStatus SAL_CALL XMLSignatureTemplateImpl::getStatus( )
+{
+ return m_nStatus;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSignatureTemplateImpl::getImplementationName() {
+ return impl_getImplementationName() ;
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSignatureTemplateImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL XMLSignatureTemplateImpl::getSupportedServiceNames() {
+ return impl_getSupportedServiceNames() ;
+}
+
+//Helper for XServiceInfo
+Sequence< OUString > XMLSignatureTemplateImpl::impl_getSupportedServiceNames() {
+ Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignatureTemplate" };
+ return seqServiceNames ;
+}
+
+OUString XMLSignatureTemplateImpl::impl_getImplementationName() {
+ return "com.sun.star.xml.security.framework.XMLSignatureTemplateImpl" ;
+}
+
+//Helper for registry
+Reference< XInterface > XMLSignatureTemplateImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) {
+ return Reference< XInterface >( *new XMLSignatureTemplateImpl ) ;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */