[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3' - include/oox oox/source sw/qa sw/source writerfilter/inc writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Fri Jun 23 14:59:40 UTC 2017


 include/oox/ole/vbaproject.hxx                |    4 +
 oox/source/core/filterdetect.cxx              |    9 ---
 oox/source/ole/vbaproject.cxx                 |   14 +++++
 sw/qa/extras/ooxmlexport/data/tdf108269.docm  |binary
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx     |   12 ++++
 sw/source/filter/ww8/docxexport.cxx           |   63 ++++++++++++++++++++++++++
 sw/source/filter/ww8/docxexport.hxx           |    3 +
 writerfilter/inc/ooxml/OOXMLDocument.hxx      |    2 
 writerfilter/source/filter/WriterFilter.cxx   |    8 +++
 writerfilter/source/ooxml/OOXMLStreamImpl.cxx |   23 ++++++++-
 10 files changed, 127 insertions(+), 11 deletions(-)

New commits:
commit 748ebf9573096d31a59cdbf5d1e65340d1d55cfa
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Jun 2 18:41:38 2017 +0200

    Related: tdf#108269 DOCM filter: preserve VBA stream
    
    This is a combination of 3 commits (initial support, then two refactor
    commits to not duplicate code.)
    
    1st commit:
    
    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).
    
    Reviewed-on: https://gerrit.libreoffice.org/38360
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 8a59b30bb1af55f7afd8b98e4b60234f98d84c76)
    
    Conflicts:
            sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
    
    Change-Id: Iba24eea4c5bca8f743a53027c71ed2aae48f1934
    
    2nd commit:
    
    Related: tdf#108269 DOCM filter: reuse oox code for VBA preservation
    
    With this, the project stream import is shared between DOCM and XLSM.
    
    Change-Id: I8fbffefc5acf28adea4875fa6bc4148a99b5ebef
    Reviewed-on: https://gerrit.libreoffice.org/38495
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>
    (cherry picked from commit e4adb8d9e77bab353dda26375e11a6b7a456368f)
    
    3rd commit:
    
    Related: tdf#108269 DOCM filter: reuse oox code for VBA data preservation
    
    Which means the DOCM-specific code to roundtrip VBA things (project,
    data) can be removed. The oox part has to be extended a bit, as at least
    for this DOCM bugdoc there is an XML relation of the binary data, while
    existing shared code assumed the full VBA project is just a single OLE
    blob.
    
    Reviewed-on: https://gerrit.libreoffice.org/38504
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>
    (cherry picked from commit 0129c2cd9dd95355412b194c595f4b986403ba1e)
    
    Conflicts:
            writerfilter/inc/ooxml/OOXMLDocument.hxx
            writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
    
    Change-Id: I4085e4dba24475e6fd555e5f34fe7ad0f305c57d
    Reviewed-on: https://gerrit.libreoffice.org/38558
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/include/oox/ole/vbaproject.hxx b/include/oox/ole/vbaproject.hxx
index c29a8eaa2ce0..e48d19a87959 100644
--- a/include/oox/ole/vbaproject.hxx
+++ b/include/oox/ole/vbaproject.hxx
@@ -37,6 +37,7 @@ namespace com { namespace sun { namespace star {
     namespace script { namespace vba { class XVBAMacroResolver; } }
     namespace uno { class XComponentContext; }
     namespace uno { class XInterface; }
+    namespace io { class XInputStream; }
 } } }
 
 namespace oox {
@@ -130,6 +131,9 @@ public:
     bool                importVbaProject(
                             StorageBase& rVbaPrjStrg );
 
+    /// Imports VBA data for a VBA project, e.g. word/vbaData.xml.
+    void                importVbaData(const css::uno::Reference<css::io::XInputStream>& xInputStream);
+
     /** Reads vba module related information from the project streams */
     void                readVbaModules( StorageBase& rVbaPrjStrg );
     /** Imports (and creates) vba modules and user forms from the vba project records previously read.
diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index 8812e0c30c25..88d3926a2656 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -172,14 +172,7 @@ void FilterDetectDocHandler::parseRelationship( const AttributeList& rAttribs )
 
 OUString FilterDetectDocHandler::getFilterNameFromContentType( const OUString& rContentType, const OUString& rFileName )
 {
-    bool bDocm = false;
-    OUString aDocmExtension = ".docm";
-    if (rFileName.getLength() >= aDocmExtension.getLength())
-    {
-        OUString aExtension = rFileName.copy(rFileName.getLength() - aDocmExtension.getLength());
-        // The file name ends with .docm, ignoring case.
-        bDocm = aExtension.equalsIgnoreAsciiCase(aDocmExtension);
-    }
+    bool bDocm = rFileName.endsWithIgnoreAsciiCase(".docm");
 
     if( rContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" && !bDocm )
         return OUString( "writer_MS_Word_2007" );
diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx
index b520d652f8d6..029d946892bd 100644
--- a/oox/source/ole/vbaproject.cxx
+++ b/oox/source/ole/vbaproject.cxx
@@ -32,6 +32,7 @@
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <comphelper/configurationhelper.hxx>
 #include <comphelper/string.hxx>
+#include <comphelper/storagehelper.hxx>
 #include <osl/diagnose.h>
 #include <rtl/tencinfo.h>
 #include <rtl/ustrbuf.h>
@@ -49,6 +50,7 @@
 namespace oox {
 namespace ole {
 
+using namespace ::com::sun::star;
 using namespace ::com::sun::star::container;
 using namespace ::com::sun::star::document;
 using namespace ::com::sun::star::embed;
@@ -182,6 +184,18 @@ void VbaProject::importVbaProject( StorageBase& rVbaPrjStrg, const GraphicHelper
     }
 }
 
+void VbaProject::importVbaData(const uno::Reference<io::XInputStream>& xInputStream)
+{
+    uno::Reference<document::XStorageBasedDocument> xStorageBasedDoc(mxDocModel, uno::UNO_QUERY);
+    uno::Reference<embed::XStorage> xDocStorage(xStorageBasedDoc->getDocumentStorage(), uno::UNO_QUERY);
+    {
+        const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
+        uno::Reference<io::XOutputStream> xDocStream(xDocStorage->openStreamElement("_MS_VBA_Macros_XML", nOpenMode), uno::UNO_QUERY);
+        comphelper::OStorageHelper::CopyInputToOutput(xInputStream, xDocStream);
+    }
+    uno::Reference<embed::XTransactedObject>(xDocStorage, uno::UNO_QUERY)->commit();
+}
+
 void VbaProject::registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher )
 {
     OSL_ENSURE( rxAttacher.get(), "VbaProject::registerMacroAttacher - unexpected empty reference" );
diff --git a/sw/qa/extras/ooxmlexport/data/tdf108269.docm b/sw/qa/extras/ooxmlexport/data/tdf108269.docm
new file mode 100644
index 000000000000..44e943531d30
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf108269.docm differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index ba0e5a207d21..aa73ed26ddad 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -90,6 +90,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(testTdf95031, "tdf95031.docx")
 {
     // This was 494, in-numbering paragraph's automating spacing was handled as visible spacing, while it should not.
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index b7cda742afb9..48b6e300ff92 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -24,6 +24,7 @@
 
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
 #include <com/sun/star/drawing/XShape.hpp>
 #include <com/sun/star/i18n/ScriptType.hpp>
 #include <com/sun/star/frame/XModel.hpp>
@@ -75,6 +76,7 @@
 #include <comphelper/string.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <vcl/font.hxx>
+#include <unotools/ucbstreamhelper.hxx>
 
 using namespace sax_fastparser;
 using namespace ::comphelper;
@@ -462,6 +464,8 @@ void DocxExport::ExportDocument_Impl()
 
     WriteEmbeddings();
 
+    WriteVBA();
+
     m_aLinkedTextboxesHelper.clear();   //final cleanup
     delete m_pStyles;
     m_pStyles = nullptr;
@@ -1247,6 +1251,65 @@ void DocxExport::WriteActiveX()
      }
 }
 
+void DocxExport::WriteVBA()
+{
+    uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
+    if (!xStorageBasedDocument.is())
+        return;
+
+    uno::Reference<embed::XStorage> xDocumentStorage(xStorageBasedDocument->getDocumentStorage(), uno::UNO_QUERY);
+    OUString aMacrosName("_MS_VBA_Macros");
+    if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName))
+        return;
+
+    const sal_Int32 nOpenMode = embed::ElementModes::READ;
+    uno::Reference<io::XStream> xMacrosStream(xDocumentStorage->openStreamElement(aMacrosName, nOpenMode), uno::UNO_QUERY);
+    uno::Reference<io::XOutputStream> xProjectStream;
+    if (xMacrosStream.is())
+    {
+        // First handle the the project stream, this sets xProjectStream.
+        std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xMacrosStream));
+
+        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");
+    }
+
+    OUString aDataName("_MS_VBA_Macros_XML");
+    if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aDataName))
+        return;
+
+    uno::Reference<io::XStream> xDataStream(xDocumentStorage->openStreamElement(aDataName, nOpenMode), uno::UNO_QUERY);
+    if (xDataStream.is())
+    {
+        // Then the data stream, which wants to work with an already set
+        // xProjectStream.
+        std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xDataStream));
+
+        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 65c9f9283730..3623c5718eeb 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();
 
diff --git a/writerfilter/inc/ooxml/OOXMLDocument.hxx b/writerfilter/inc/ooxml/OOXMLDocument.hxx
index af060387d9a7..1b33336c8996 100644
--- a/writerfilter/inc/ooxml/OOXMLDocument.hxx
+++ b/writerfilter/inc/ooxml/OOXMLDocument.hxx
@@ -75,7 +75,7 @@ class OOXMLStream
 {
 public:
     enum StreamType_t { UNKNOWN, DOCUMENT, STYLES, WEBSETTINGS, FONTTABLE, NUMBERING,
-        FOOTNOTES, ENDNOTES, COMMENTS, THEME, CUSTOMXML, CUSTOMXMLPROPS, ACTIVEX, ACTIVEXBIN, GLOSSARY, CHARTS, EMBEDDINGS, SETTINGS, VBAPROJECT, FOOTER, HEADER, SIGNATURE };
+        FOOTNOTES, ENDNOTES, COMMENTS, THEME, CUSTOMXML, CUSTOMXMLPROPS, ACTIVEX, ACTIVEXBIN, GLOSSARY, CHARTS, EMBEDDINGS, SETTINGS, VBAPROJECT, FOOTER, HEADER, SIGNATURE, VBADATA };
     typedef std::shared_ptr<OOXMLStream> Pointer_t;
 
     virtual ~OOXMLStream() {}
diff --git a/writerfilter/source/filter/WriterFilter.cxx b/writerfilter/source/filter/WriterFilter.cxx
index b50a8f49743f..4a1ce7762e3c 100644
--- a/writerfilter/source/filter/WriterFilter.cxx
+++ b/writerfilter/source/filter/WriterFilter.cxx
@@ -254,6 +254,14 @@ sal_Bool WriterFilter::filter(const uno::Sequence< beans::PropertyValue >& aDesc
 
             oox::GraphicHelper gHelper(m_xContext, xFrame, xVbaPrjStrg);
             aVbaProject.importVbaProject(*xVbaPrjStrg, gHelper);
+
+            writerfilter::ooxml::OOXMLStream::Pointer_t pVBADataStream(writerfilter::ooxml::OOXMLDocumentFactory::createStream(pDocStream, writerfilter::ooxml::OOXMLStream::VBADATA));
+            if (pVBADataStream)
+            {
+                uno::Reference<io::XInputStream> xDataStream = pVBADataStream->getDocumentStream();
+                if (xDataStream.is())
+                    aVbaProject.importVbaData(xDataStream);
+            }
         }
 
         pStream.reset();
diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
index 16d7ae31100b..fe26b58cbe93 100644
--- a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
@@ -173,6 +173,7 @@ bool OOXMLStreamImpl::lcl_getTarget(const uno::Reference<embed::XRelationshipAcc
     static const char sHeaderTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/header";
     static const char sOleObjectTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/oleObject";
     static const char sVBAProjectType[] = "http://schemas.microsoft.com/office/2006/relationships/vbaProject";
+    static const char sVBADataType[] = "http://schemas.microsoft.com/office/2006/relationships/wordVbaData";
 
     OUString sStreamType;
     OUString sStreamTypeStrict;
@@ -183,6 +184,10 @@ bool OOXMLStreamImpl::lcl_getTarget(const uno::Reference<embed::XRelationshipAcc
             sStreamType = sVBAProjectType;
             sStreamTypeStrict = sVBAProjectType;
             break;
+        case VBADATA:
+            sStreamType = sVBADataType;
+            sStreamTypeStrict = sVBADataType;
+            break;
         case DOCUMENT:
             sStreamType = sDocumentType;
             sStreamTypeStrict = sDocumentTypeStrict;
@@ -420,8 +425,22 @@ OOXMLDocumentFactory::createStream
 (const OOXMLStream::Pointer_t& pStream,  OOXMLStream::StreamType_t nStreamType)
 {
     OOXMLStream::Pointer_t pRet;
-    if (OOXMLStreamImpl* pImpl = dynamic_cast<OOXMLStreamImpl *>(pStream.get()))
-        pRet.reset(new OOXMLStreamImpl(*pImpl, nStreamType));
+
+    if (nStreamType != OOXMLStream::VBADATA)
+    {
+        if (OOXMLStreamImpl* pImpl = dynamic_cast<OOXMLStreamImpl *>(pStream.get()))
+            pRet.reset(new OOXMLStreamImpl(*pImpl, nStreamType));
+    }
+    else
+    {
+        // VBADATA is not a relation of the document, but of the VBAPROJECT stream.
+        if (OOXMLStreamImpl* pImpl = dynamic_cast<OOXMLStreamImpl *>(pStream.get()))
+        {
+            std::unique_ptr<OOXMLStreamImpl> pProject(new OOXMLStreamImpl(*pImpl, OOXMLStream::VBAPROJECT));
+            pRet.reset(new OOXMLStreamImpl(*pProject, OOXMLStream::VBADATA));
+        }
+    }
+
     return pRet;
 }
 


More information about the Libreoffice-commits mailing list