diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-06-02 18:41:38 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-06-02 21:31:01 +0200 |
commit | 8a59b30bb1af55f7afd8b98e4b60234f98d84c76 (patch) | |
tree | d71bcd1ecfc93ccd1720d41f74edd9150c58fc8e /sw | |
parent | ecad6d749726dbb8c945f67fca3856cbd2ff4851 (diff) |
Related: tdf#108269 DOCM filter: preserve VBA stream
This means 2 new streams when roundtripping DOCM files that actually
have macros: word/vbaProject.bin and word/vbaData.xml (+ the relation
pointing to the second from the first).
Change-Id: Iba24eea4c5bca8f743a53027c71ed2aae48f1934
Reviewed-on: https://gerrit.libreoffice.org/38360
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf108269.docm | bin | 0 -> 20187 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 12 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 75 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.hxx | 3 |
4 files changed, 90 insertions, 0 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf108269.docm b/sw/qa/extras/ooxmlexport/data/tdf108269.docm Binary files differnew file mode 100644 index 000000000000..44e943531d30 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf108269.docm diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index 0191b8a38023..a7aadf16549f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -93,6 +93,18 @@ DECLARE_SW_ROUNDTRIP_TEST(testBadDocm, "bad.docm", nullptr, DocmTest) CPPUNIT_ASSERT_EQUAL(OUString("MS Word 2007 XML VBA"), pTextDoc->GetDocShell()->GetMedium()->GetFilter()->GetName()); } +DECLARE_SW_ROUNDTRIP_TEST(testTdf108269, "tdf108269.docm", nullptr, DocmTest) +{ + if (!mbExported) + return; + + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); + // This failed: VBA streams were not roundtripped via the doc-level + // grab-bag. + CPPUNIT_ASSERT(xNameAccess->hasByName("word/vbaProject.bin")); + CPPUNIT_ASSERT(xNameAccess->hasByName("word/vbaData.xml")); +} + DECLARE_OOXMLEXPORT_TEST(testTdf92045, "tdf92045.docx") { // This was true, <w:effect w:val="none"/> resulted in setting the blinking font effect. diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 57432c9add87..a57eb02915c8 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -77,6 +77,7 @@ #include <comphelper/string.hxx> #include <rtl/ustrbuf.hxx> #include <vcl/font.hxx> +#include <unotools/ucbstreamhelper.hxx> using namespace sax_fastparser; using namespace ::comphelper; @@ -464,6 +465,8 @@ void DocxExport::ExportDocument_Impl() WriteEmbeddings(); + WriteVBA(); + m_aLinkedTextboxesHelper.clear(); //final cleanup delete m_pStyles; m_pStyles = nullptr; @@ -1251,6 +1254,78 @@ void DocxExport::WriteActiveX() } } +void DocxExport::WriteVBA() +{ + uno::Reference<beans::XPropertySet> xPropertySet(m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY); + if (!xPropertySet.is()) + return; + + uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo(); + if (!xPropertySetInfo->hasPropertyByName(UNO_NAME_MISC_OBJ_INTEROPGRABBAG)) + return; + + uno::Sequence<beans::PropertyValue> aGrabBag; + xPropertySet->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG) >>= aGrabBag; + uno::Sequence<beans::PropertyValue> aVBA; + for (const auto& rProperty : aGrabBag) + { + if (rProperty.Name == "OOXVBA") + rProperty.Value >>= aVBA; + } + if (!aVBA.hasElements()) + return; + + uno::Reference<io::XOutputStream> xProjectStream; + for (const auto& rProperty : aVBA) + { + if (rProperty.Name == "ProjectStream") + { + // First check for the project stream, this sets xProjectStream. + uno::Reference<io::XStream> xInputStream; + rProperty.Value >>= xInputStream; + if (!xInputStream.is()) + return; + std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xInputStream)); + + xProjectStream = GetFilter().openFragmentStream("word/vbaProject.bin", "application/vnd.ms-office.vbaProject"); + uno::Reference<io::XStream> xOutputStream(xProjectStream, uno::UNO_QUERY); + if (!xOutputStream.is()) + return; + std::unique_ptr<SvStream> pOut(utl::UcbStreamHelper::CreateStream(xOutputStream)); + + // Write the stream. + pOut->WriteStream(*pIn); + + // Write the relationship. + m_pFilter->addRelation(m_pDocumentFS->getOutputStream(), "http://schemas.microsoft.com/office/2006/relationships/vbaProject", "vbaProject.bin"); + } + else if (rProperty.Name == "DataStream") + { + // Then the data stream, which wants to work with an already set + // xProjectStream. + uno::Reference<io::XStream> xInputStream; + rProperty.Value >>= xInputStream; + if (!xInputStream.is()) + return; + std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xInputStream)); + + uno::Reference<io::XStream> xOutputStream(GetFilter().openFragmentStream("word/vbaData.xml", "application/vnd.ms-word.vbaData+xml"), uno::UNO_QUERY); + if (!xOutputStream.is()) + return; + std::unique_ptr<SvStream> pOut(utl::UcbStreamHelper::CreateStream(xOutputStream)); + + // Write the stream. + pOut->WriteStream(*pIn); + + // Write the relationship. + if (!xProjectStream.is()) + return; + + m_pFilter->addRelation(xProjectStream, "http://schemas.microsoft.com/office/2006/relationships/wordVbaData", "vbaData.xml"); + } + } +} + void DocxExport::WriteEmbeddings() { uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 454e0742cee1..b3627639eb96 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -244,6 +244,9 @@ private: /// Write word/embeddings/Worksheet[n].xlsx void WriteEmbeddings(); + /// Writes word/vbaProject.bin. + void WriteVBA(); + /// return true if Page Layout is set as Mirrored bool isMirroredMargin(); |