From da100343e5416e1040f8f6d83fd73d8d0577112e Mon Sep 17 00:00:00 2001 From: Vasily Melenchuk Date: Sun, 11 Sep 2022 15:46:09 +0300 Subject: [PATCH] tdf#147724: DOCX STD import: use storeid to indetify custom XML We need to identify XML document to use by storeid in sdt block and in properties of external XML file. Otherwise are possible content collisions when same xpath can evaluate successfully absolutely unrelated custom XML. Change-Id: I6d201a539130b110046deb1818340513cc47a061 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139771 Tested-by: Jenkins Reviewed-by: Vasily Melenchuk --- sw/qa/extras/ooxmlexport/data/tdf147724.docx | Bin 0 -> 9928 bytes sw/qa/extras/ooxmlexport/ooxmlexport18.cxx | 13 ++++ writerfilter/source/dmapper/SdtHelper.cxx | 64 ++++++++++++++++--- writerfilter/source/dmapper/SdtHelper.hxx | 3 +- 4 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 sw/qa/extras/ooxmlexport/data/tdf147724.docx diff --git a/sw/qa/extras/ooxmlexport/data/tdf147724.docx b/sw/qa/extras/ooxmlexport/data/tdf147724.docx new file mode 100644 index 0000000000000000000000000000000000000000..97f05c921b89ab04537459f938b35b58d4a4a586 GIT binary patch literal 9928 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 *ABC*"); + + // This SDT has no storage id, it is not an error, but content can be taken from any suitable XML + // There 2 variants possible, both are acceptable + OUString sFieldResult = getXPathContent(pLayout, "/root/page[1]/body/txt[2]"); + CPPUNIT_ASSERT(sFieldResult == "Placeholder -> *HERUNTERLADEN*" || sFieldResult == "Placeholder -> *ABC*"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 50ddf4b99b21..8225a6a04bca 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -104,13 +104,13 @@ void SdtHelper::loadPropertiesXMLs() if (!xDomBuilder.is()) return; - std::vector> aPropDocs; - // Load core properties try { auto xCorePropsStream = xImporter->getCorePropertiesStream(m_rDM_Impl.m_xDocumentStorage); - aPropDocs.push_back(xDomBuilder->parse(xCorePropsStream)); + m_xPropertiesXMLs.insert( + { OUString("{6C3C8BC8-F283-45AE-878A-BAB7291924A1}"), // hardcoded id for core props + xDomBuilder->parse(xCorePropsStream) }); } catch (const uno::Exception&) { @@ -123,7 +123,9 @@ void SdtHelper::loadPropertiesXMLs() { auto xExtPropsStream = xImporter->getExtendedPropertiesStream(m_rDM_Impl.m_xDocumentStorage); - aPropDocs.push_back(xDomBuilder->parse(xExtPropsStream)); + m_xPropertiesXMLs.insert( + { OUString("{6668398D-A668-4E3E-A5EB-62B293D839F1}"), // hardcoded id for extended props + xDomBuilder->parse(xExtPropsStream) }); } catch (const uno::Exception&) { @@ -136,12 +138,40 @@ void SdtHelper::loadPropertiesXMLs() // Add custom XMLs uno::Sequence> aCustomXmls = m_rDM_Impl.getDocumentReference()->getCustomXmlDomList(); - for (const auto& xDoc : aCustomXmls) + uno::Sequence> aCustomXmlProps + = m_rDM_Impl.getDocumentReference()->getCustomXmlDomPropsList(); + if (aCustomXmls.getLength()) { - aPropDocs.push_back(xDoc); + uno::Reference xXpathAPI = XPathAPI::create(m_xComponentContext); + xXpathAPI->registerNS("ds", + "http://schemas.openxmlformats.org/officeDocument/2006/customXml"); + sal_Int32 nItem = 0; + // Hereby we assume that items from getCustomXmlDomList() and getCustomXmlDomPropsList() + // are matching each other: + // item1.xml -> itemProps1.xml, item2.xml -> itemProps2.xml + // This does works practically, but is it true in general? + for (const auto& xDoc : aCustomXmls) + { + // Retrieve storeid from properties xml + OUString aStoreId; + uno::Reference xResult + = xXpathAPI->eval(aCustomXmlProps[nItem], "string(/ds:datastoreItem/@ds:itemID)"); + + if (xResult.is() && xResult->getString().getLength()) + { + aStoreId = xResult->getString(); + } + else + { + SAL_WARN("writerfilter", + "SdtHelper::loadPropertiesXMLs: can't fetch storeid for custom doc!"); + } + + m_xPropertiesXMLs.insert({ aStoreId, xDoc }); + nItem++; + } } - m_xPropertiesXMLs = comphelper::containerToSequence(aPropDocs); m_bPropertiesXMLsLoaded = true; } @@ -191,10 +221,24 @@ std::optional SdtHelper::getValueFromDataBinding() lcl_registerNamespaces(m_sDataBindingPrefixMapping, xXpathAPI); - // Iterate all properties xml documents and try to fetch data - for (const auto& xDocument : m_xPropertiesXMLs) + // Find storage by store id and eval xpath there + const auto& aSourceIt = m_xPropertiesXMLs.find(m_sDataBindingStoreItemID); + if (aSourceIt != m_xPropertiesXMLs.end()) { - uno::Reference xResult = xXpathAPI->eval(xDocument, m_sDataBindingXPath); + uno::Reference xResult + = xXpathAPI->eval(aSourceIt->second, m_sDataBindingXPath); + + if (xResult.is() && xResult->getNodeList() && xResult->getNodeList()->getLength() + && xResult->getString().getLength()) + { + return xResult->getString(); + } + } + + // Nothing found? Try to iterate storages and eval xpath + for (const auto& aSource : m_xPropertiesXMLs) + { + uno::Reference xResult = xXpathAPI->eval(aSource.second, m_sDataBindingXPath); if (xResult.is() && xResult->getNodeList() && xResult->getNodeList()->getLength() && xResult->getString().getLength()) diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index 2cfa19f5e95e..689c57503185 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -94,7 +95,7 @@ class SdtHelper final : public virtual SvRefBase bool m_bOutsideAParagraph; /// Storage for all properties documents as xml::dom::XDocument for later querying xpath for data - css::uno::Sequence> m_xPropertiesXMLs; + std::unordered_map> m_xPropertiesXMLs; /// Check if m_xPropertiesXMLs is initialized and loaded (need extra flag to distinguish /// empty sequence from not yet initialized)