[Libreoffice-commits] core.git: filter/source sw/CppunitTest_sw_htmlexport.mk sw/qa

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Mon May 4 09:28:35 UTC 2020


 filter/source/msfilter/rtfutil.cxx     |   82 ++++++++++++++++++++++++++++++++-
 sw/CppunitTest_sw_htmlexport.mk        |    1 
 sw/qa/extras/htmlexport/htmlexport.cxx |   31 ++++++++++++
 3 files changed, 112 insertions(+), 2 deletions(-)

New commits:
commit 800085d4fb0831f2065e86bfd99164cd89998fcd
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon May 4 10:48:07 2020 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon May 4 11:27:54 2020 +0200

    sw reqif-xhtml import, embedded objects: handle Ole10Native stream
    
    This is the import side of commit
    1392fd6a7eaf9f507639096984c2a0108f254795 (sw reqif-xhtml export,
    embedded objects: handle Ole10Native stream, 2020-04-30).
    
    Change-Id: Ib98620f06c471a58e75b0e6c0230d37820dbc928
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93402
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx
index ccce7609820c..b347d5726d8d 100644
--- a/filter/source/msfilter/rtfutil.cxx
+++ b/filter/source/msfilter/rtfutil.cxx
@@ -14,6 +14,68 @@
 #include <svtools/rtfkeywd.hxx>
 #include <rtl/character.hxx>
 #include <tools/stream.hxx>
+#include <sot/stg.hxx>
+#include <sot/storage.hxx>
+
+namespace
+{
+/// If rOle1 is native OLE1 data of size nOle1Size, wraps it in an OLE2 container.
+void WrapOle1InOle2(SvStream& rOle1, sal_uInt32 nOle1Size, SvStream& rOle2)
+{
+    tools::SvRef<SotStorage> pStorage = new SotStorage(rOle2);
+    // OLE Package Object
+    SvGlobalName aName(0x0003000C, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46);
+    pStorage->SetClass(aName, SotClipboardFormatId::NONE, "");
+
+    // [MS-OLEDS] 2.3.7 CompObjHeader
+    tools::SvRef<SotStorageStream> pCompObj = pStorage->OpenSotStream("\1CompObj");
+    // Reserved1
+    pCompObj->WriteUInt32(0xfffe0001);
+    // Version
+    pCompObj->WriteUInt32(0x00000a03);
+    // Reserved2
+    pCompObj->WriteUInt32(0xffffffff);
+    pCompObj->WriteUInt32(0x0003000c);
+    pCompObj->WriteUInt32(0x00000000);
+    pCompObj->WriteUInt32(0x000000c0);
+    pCompObj->WriteUInt32(0x46000000);
+    // Rest of CompObjStream
+    // AnsiUserType
+    OString aAnsiUserType("OLE Package");
+    pCompObj->WriteUInt32(aAnsiUserType.getLength() + 1);
+    pCompObj->WriteOString(aAnsiUserType);
+    pCompObj->WriteChar(0);
+    // AnsiClipboardFormat
+    pCompObj->WriteUInt32(0x00000000);
+    // Reserved1
+    OString aReserved1("Package");
+    pCompObj->WriteUInt32(aReserved1.getLength() + 1);
+    pCompObj->WriteOString(aReserved1);
+    pCompObj->WriteChar(0);
+    // UnicodeMarker
+    pCompObj->WriteUInt32(0x71B239F4);
+    // UnicodeUserType
+    pCompObj->WriteUInt32(0x00000000);
+    // UnicodeClipboardFormat
+    pCompObj->WriteUInt32(0x00000000);
+    // Reserved2
+    pCompObj->WriteUInt32(0x00000000);
+    pCompObj->Commit();
+    pCompObj.clear();
+
+    // [MS-OLEDS] 2.3.6 OLENativeStream
+    tools::SvRef<SotStorageStream> pOleNative = pStorage->OpenSotStream("\1Ole10Native");
+    // NativeDataSize
+    pOleNative->WriteUInt32(nOle1Size);
+    pOleNative->WriteStream(rOle1, nOle1Size);
+    pOleNative->Commit();
+    pOleNative.clear();
+
+    pStorage->Commit();
+    pStorage.clear();
+    rOle2.Seek(0);
+}
+}
 
 namespace msfilter::rtfutil
 {
@@ -278,8 +340,24 @@ bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
 
         if (nData)
         {
-            // NativeData
-            rOle2.WriteStream(aStream, nData);
+            sal_uInt64 nPos = aStream.Tell();
+            sal_uInt8 aSignature[8];
+            aStream.ReadBytes(aSignature, SAL_N_ELEMENTS(aSignature));
+            aStream.Seek(nPos);
+            const sal_uInt8 aOle2Signature[8] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
+            // Don't use Storage::IsStorageFile() here, that would seek to the start of the stream,
+            // where the magic will always mismatch.
+            if (std::memcmp(aSignature, aOle2Signature, SAL_N_ELEMENTS(aSignature)) == 0)
+            {
+                // NativeData
+                rOle2.WriteStream(aStream, nData);
+            }
+            else
+            {
+                SvMemoryStream aStorage;
+                WrapOle1InOle2(aStream, nData, aStorage);
+                rOle2.WriteStream(aStorage);
+            }
             rOle2.Seek(0);
         }
     }
diff --git a/sw/CppunitTest_sw_htmlexport.mk b/sw/CppunitTest_sw_htmlexport.mk
index c85c5b8212cd..f1e2342ad1ba 100644
--- a/sw/CppunitTest_sw_htmlexport.mk
+++ b/sw/CppunitTest_sw_htmlexport.mk
@@ -25,6 +25,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_htmlexport, \
 	msfilter \
     sal \
     sfx \
+    sot \
     sw \
     svt \
     test \
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 54334aade9f5..d05da8ad4943 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -32,6 +32,7 @@
 #include <rtl/strbuf.hxx>
 #include <svtools/rtftoken.h>
 #include <filter/msfilter/rtfutil.hxx>
+#include <sot/storage.hxx>
 
 class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
 {
@@ -1019,6 +1020,36 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PDF)
     // i.e. we did not work with the Ole10Native stream, rather created an OLE1 wrapper around the
     // OLE1-in-OLE2 data, resulting in additional size.
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0x99ed), nData);
+
+    // Now import this back and check the ODT result.
+    mxComponent->dispose();
+    mxComponent.clear();
+    uno::Sequence<beans::PropertyValue> aLoadProperties = {
+        comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")),
+        comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")),
+    };
+    mxComponent
+        = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument", aLoadProperties);
+    xStorable.set(mxComponent, uno::UNO_QUERY);
+    utl::TempFile aTempFile;
+    aStoreProperties = {
+        comphelper::makePropertyValue("FilterName", OUString("writer8")),
+    };
+    xStorable->storeToURL(aTempFile.GetURL(), aStoreProperties);
+    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
+        = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory),
+                                                      aTempFile.GetURL());
+    uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName("Object 2"),
+                                                  uno::UNO_QUERY);
+    std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+    tools::SvRef<SotStorage> pStorage = new SotStorage(*pStream);
+    tools::SvRef<SotStorageStream> pOleNative = pStorage->OpenSotStream("\1Ole10Native");
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 39409
+    // - Actual  : 0
+    // i.e. we didn't handle the case when the ole1 payload was not an ole2 container. Note how the
+    // expected value is the same as nData above + 4 bytes, since this data is length-prefixed.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(39409), pOleNative->GetSize());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();


More information about the Libreoffice-commits mailing list