From 9b9bc7461e0513e2bb493e7f00f800b2463751e1 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Wed, 18 Jan 2023 20:58:47 +0100 Subject: [PATCH] tdf#153039 unoxml: replace root element of CDocument throws XForms replace doesn't work because: CDocument::IsChildTypeAllowed() tests that the document node does not already have an element child, because only one is allowed - but when called from CNode::replaceChild(), the existing child will be removed, so that needs to be allowed to proceed (check that removed child is also element). (regression from commit c5db3b93ee1058bd20ebcde2e757b52b9a67b74a) Change-Id: I167de3462f4d1934dbf8404ad395349897cfd981 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145757 Tested-by: Jenkins Reviewed-by: Noel Grandin --- unoxml/inc/node.hxx | 3 ++- unoxml/source/dom/attr.cxx | 2 +- unoxml/source/dom/attr.hxx | 3 ++- unoxml/source/dom/document.cxx | 8 +++++--- unoxml/source/dom/document.hxx | 3 ++- unoxml/source/dom/documentfragment.cxx | 2 +- unoxml/source/dom/documentfragment.hxx | 3 ++- unoxml/source/dom/element.cxx | 2 +- unoxml/source/dom/element.hxx | 3 ++- unoxml/source/dom/entity.cxx | 2 +- unoxml/source/dom/entity.hxx | 3 ++- unoxml/source/dom/entityreference.cxx | 2 +- unoxml/source/dom/entityreference.hxx | 3 ++- unoxml/source/dom/node.cxx | 8 ++++---- 14 files changed, 28 insertions(+), 19 deletions(-) diff --git a/unoxml/inc/node.hxx b/unoxml/inc/node.hxx index c4933dbdc234..17e474bf9683 100644 --- a/unoxml/inc/node.hxx +++ b/unoxml/inc/node.hxx @@ -134,7 +134,8 @@ namespace DOM virtual void fastSaxify( Context& io_rContext ); // constrains child relationship between nodes based on type - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType); + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType nodeType, + css::xml::dom::NodeType const* pReplacedNodeType); // ---- DOM interfaces diff --git a/unoxml/source/dom/attr.cxx b/unoxml/source/dom/attr.cxx index 1a993e152bd7..4988aa4211ec 100644 --- a/unoxml/source/dom/attr.cxx +++ b/unoxml/source/dom/attr.cxx @@ -70,7 +70,7 @@ namespace DOM return pNs; } - bool CAttr::IsChildTypeAllowed(NodeType const nodeType) + bool CAttr::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const) { switch (nodeType) { case NodeType_TEXT_NODE: diff --git a/unoxml/source/dom/attr.hxx b/unoxml/source/dom/attr.hxx index 30c0aa25bb34..f30b25896158 100644 --- a/unoxml/source/dom/attr.hxx +++ b/unoxml/source/dom/attr.hxx @@ -52,7 +52,8 @@ namespace DOM /// return the libxml namespace corresponding to m_pNamespace on pNode xmlNsPtr GetNamespace(xmlNodePtr const pNode); - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override; + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, + css::xml::dom::NodeType const*) override; /** Returns the name of this attribute. diff --git a/unoxml/source/dom/document.cxx b/unoxml/source/dom/document.cxx index 49c524b5ee99..413f764815e5 100644 --- a/unoxml/source/dom/document.cxx +++ b/unoxml/source/dom/document.cxx @@ -291,7 +291,7 @@ namespace DOM rContext.mxDocHandler->endDocument(); } - bool CDocument::IsChildTypeAllowed(NodeType const nodeType) + bool CDocument::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const pReplacedNodeType) { switch (nodeType) { case NodeType_PROCESSING_INSTRUCTION_NODE: @@ -299,10 +299,12 @@ namespace DOM return true; case NodeType_ELEMENT_NODE: // there may be only one! - return nullptr == lcl_getDocumentRootPtr(m_aDocPtr); + return (pReplacedNodeType && *pReplacedNodeType == nodeType) + || nullptr == lcl_getDocumentRootPtr(m_aDocPtr); case NodeType_DOCUMENT_TYPE_NODE: // there may be only one! - return nullptr == lcl_getDocumentType(m_aDocPtr); + return (pReplacedNodeType && *pReplacedNodeType == nodeType) + || nullptr == lcl_getDocumentType(m_aDocPtr); default: return false; } diff --git a/unoxml/source/dom/document.hxx b/unoxml/source/dom/document.hxx index 291535ebf8e5..450b9200f86f 100644 --- a/unoxml/source/dom/document.hxx +++ b/unoxml/source/dom/document.hxx @@ -114,7 +114,8 @@ namespace DOM virtual void fastSaxify( Context& rContext ) override; - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override; + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, + css::xml::dom::NodeType const* pReplacedNodeType) override; /** Creates an Attr of the given name. diff --git a/unoxml/source/dom/documentfragment.cxx b/unoxml/source/dom/documentfragment.cxx index 62c69b4db8e5..dd3ed3c18f54 100644 --- a/unoxml/source/dom/documentfragment.cxx +++ b/unoxml/source/dom/documentfragment.cxx @@ -32,7 +32,7 @@ namespace DOM { } - bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType) + bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const) { switch (nodeType) { case NodeType_ELEMENT_NODE: diff --git a/unoxml/source/dom/documentfragment.hxx b/unoxml/source/dom/documentfragment.hxx index 7bb3c187b236..c71edc86a78d 100644 --- a/unoxml/source/dom/documentfragment.hxx +++ b/unoxml/source/dom/documentfragment.hxx @@ -40,7 +40,8 @@ namespace DOM xmlNodePtr const pNode); public: - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override; + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, + css::xml::dom::NodeType const*) override; // ---- resolve uno inheritance problems... // overrides for XNode base diff --git a/unoxml/source/dom/element.cxx b/unoxml/source/dom/element.cxx index 06917c1f400e..6f60c8d950d2 100644 --- a/unoxml/source/dom/element.cxx +++ b/unoxml/source/dom/element.cxx @@ -202,7 +202,7 @@ namespace DOM popContext(i_rContext); } - bool CElement::IsChildTypeAllowed(NodeType const nodeType) + bool CElement::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const) { switch (nodeType) { case NodeType_ELEMENT_NODE: diff --git a/unoxml/source/dom/element.hxx b/unoxml/source/dom/element.hxx index efa048bfe2e1..3810e0935379 100644 --- a/unoxml/source/dom/element.hxx +++ b/unoxml/source/dom/element.hxx @@ -53,7 +53,8 @@ namespace DOM virtual void fastSaxify( Context& i_rContext ) override; - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override; + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, + css::xml::dom::NodeType const*) override; /** Retrieves an attribute value by name. diff --git a/unoxml/source/dom/entity.cxx b/unoxml/source/dom/entity.cxx index 74b1faaf7e75..ccc8a0872499 100644 --- a/unoxml/source/dom/entity.cxx +++ b/unoxml/source/dom/entity.cxx @@ -37,7 +37,7 @@ namespace DOM { } - bool CEntity::IsChildTypeAllowed(NodeType const nodeType) + bool CEntity::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const) { switch (nodeType) { case NodeType_ELEMENT_NODE: diff --git a/unoxml/source/dom/entity.hxx b/unoxml/source/dom/entity.hxx index 612c06502566..2668adb68701 100644 --- a/unoxml/source/dom/entity.hxx +++ b/unoxml/source/dom/entity.hxx @@ -45,7 +45,8 @@ namespace DOM xmlEntityPtr const pEntity); public: - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override; + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, + css::xml::dom::NodeType const*) override; /** For unparsed entities, the name of the notation for the entity. diff --git a/unoxml/source/dom/entityreference.cxx b/unoxml/source/dom/entityreference.cxx index f94496d7b705..a3a06a238130 100644 --- a/unoxml/source/dom/entityreference.cxx +++ b/unoxml/source/dom/entityreference.cxx @@ -34,7 +34,7 @@ namespace DOM { } - bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType) + bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const) { switch (nodeType) { case NodeType_ELEMENT_NODE: diff --git a/unoxml/source/dom/entityreference.hxx b/unoxml/source/dom/entityreference.hxx index 05fd330af785..2ed9f568b7a8 100644 --- a/unoxml/source/dom/entityreference.hxx +++ b/unoxml/source/dom/entityreference.hxx @@ -43,7 +43,8 @@ namespace DOM xmlNodePtr const pNode); public: - virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override; + virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, + css::xml::dom::NodeType const*) override; // ---- resolve uno inheritance problems... // overrides for XNode base diff --git a/unoxml/source/dom/node.cxx b/unoxml/source/dom/node.cxx index c60c5e9a0bb3..2e3f56c68957 100644 --- a/unoxml/source/dom/node.cxx +++ b/unoxml/source/dom/node.cxx @@ -256,7 +256,7 @@ namespace DOM // default: do nothing } - bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/) + bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/, NodeType const*const) { // default: no children allowed return false; @@ -314,7 +314,7 @@ namespace DOM } checkNoParent(cur); - if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) { + if (!IsChildTypeAllowed(pNewChild->m_aNodeType, nullptr)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e; @@ -648,7 +648,7 @@ namespace DOM // already has parent checkNoParent(pNewChild); - if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + if (!IsChildTypeAllowed(pNewNode->m_aNodeType, nullptr)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e; @@ -817,7 +817,7 @@ namespace DOM // already has parent checkNoParent(pNew); - if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + if (!IsChildTypeAllowed(pNewNode->m_aNodeType, &pOldNode->m_aNodeType)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e;