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(-)

New commits:
commit f91be4463ee303b11ec4b60186e9fbec390f7f11
Author:     Michael Stahl <[email protected]>
AuthorDate: Wed Jan 18 20:58:47 2023 +0100
Commit:     Caolán McNamara <[email protected]>
CommitDate: Thu Jan 19 19:40:53 2023 +0000

    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 <[email protected]>
    (cherry picked from commit 9b9bc7461e0513e2bb493e7f00f800b2463751e1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145788
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/unoxml/inc/node.hxx b/unoxml/inc/node.hxx
index e6974271f83a..bc93c5871b55 100644
--- a/unoxml/inc/node.hxx
+++ b/unoxml/inc/node.hxx
@@ -130,7 +130,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 481b071e62e5..61109de6b85c 100644
--- a/unoxml/source/dom/element.cxx
+++ b/unoxml/source/dom/element.cxx
@@ -203,7 +203,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 235af0bc5e0d..32cbedc0ef4b 100644
--- a/unoxml/source/dom/node.cxx
+++ b/unoxml/source/dom/node.cxx
@@ -262,7 +262,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;
@@ -301,7 +301,7 @@ namespace DOM
             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
             throw e;
         }
-        if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
+        if (!IsChildTypeAllowed(pNewChild->m_aNodeType, nullptr)) {
             DOMException e;
             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
             throw e;
@@ -642,7 +642,7 @@ namespace DOM
             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
             throw e;
         }
-        if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
+        if (!IsChildTypeAllowed(pNewNode->m_aNodeType, nullptr)) {
             DOMException e;
             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
             throw e;
@@ -822,7 +822,7 @@ namespace DOM
             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
             throw e;
         }
-        if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
+        if (!IsChildTypeAllowed(pNewNode->m_aNodeType, 
&pOldNode->m_aNodeType)) {
             DOMException e;
             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
             throw e;

Reply via email to