[Libreoffice-commits] core.git: Branch 'distro/vector/vector-5.4' - filter/source sw/qa sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Nov 21 09:27:45 UTC 2018


 filter/source/msfilter/rtfutil.cxx        |    6 +
 sw/qa/extras/htmlexport/htmlexport.cxx    |   12 +--
 sw/source/filter/html/htmlreqifreader.cxx |   93 ++++++++++++++++++++++++++++--
 3 files changed, 96 insertions(+), 15 deletions(-)

New commits:
commit 2462b9831b87696fb40bfcaa56e96f4fefbf0d99
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Nov 20 17:31:02 2018 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed Nov 21 10:18:55 2018 +0100

    sw reqif-xhtml export: write graphic of OLE object at OLE1 level
    
    [MS-OLEDS] 2.2.5 EmbeddedObject actually has a last Presentation field,
    and we didn't write it so far.
    
    Luckily all the info can be extracted from the OLE2 container, so we can
    roundtrip the OLE1 wrapper around OLE2 nicely.
    
    Reviewed-on: https://gerrit.libreoffice.org/63667
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 1ca409292272632f443733450313de5a82c54a9c)
    
    Change-Id: I8d4922428dd5beeaae8b6cd4da0575db7014e4a2

diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx
index cdb3d7d4acce..ee7b4c7b74bc 100644
--- a/filter/source/msfilter/rtfutil.cxx
+++ b/filter/source/msfilter/rtfutil.cxx
@@ -14,6 +14,7 @@
 #include <rtl/character.hxx>
 #include <tools/stream.hxx>
 #include <unotools/streamwrap.hxx>
+#include <vector>
 
 namespace msfilter
 {
@@ -276,7 +277,10 @@ bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
 
         if (nData)
         {
-            rOle2.WriteStream(aStream);
+            // NativeData
+            std::vector<char> aBuffer(nData);
+            aStream.ReadBytes(aBuffer.data(), aBuffer.size());
+            rOle2.WriteBytes(aBuffer.data(), aBuffer.size());
             rOle2.Seek(0);
         }
     }
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index a79cc2df55c6..95ed4ba88a2a 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -569,14 +569,10 @@ DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfOle2, "reqif-ole2.xhtml")
     // filter to handle it, so nothing happened on double-click.
     CPPUNIT_ASSERT(xEmbeddedObject.is());
     uno::Reference<io::XSeekable> xStream(xEmbeddedObject->getStream(), uno::UNO_QUERY);
-    // This was 80913, the RTF hexdump -> OLE1 binary -> OLE2 conversion was
-    // missing.
-    // Also, this was 38912 when we re-generated the OLE2 preview, which is
-    // wrong, the OLE2 data is 38375 bytes in the ole2.ole (referenced by
-    // reqif-ole2.xhtml). To see that this is the correct value, convert the
-    // hexdump in ole2.ole to binary, remove the ole1 header and check the byte
-    // size.
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(38375), xStream->getLength());
+    // This was 38375, msfilter::rtfutil::ExtractOLE2FromObjdata() wrote
+    // everything after the OLE1 header into the OLE2 stream, while the
+    // Presentation field after the OLE2 data doesn't belong there.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(37888), xStream->getLength());
     // Finally the export also failed as it tried to open the stream from the
     // document storage, but the embedded object already opened it, so an
     // exception of type com.sun.star.io.IOException was thrown.
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index f952a06c9c2e..9f657663b126 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -93,8 +93,59 @@ OString ExtractOLEClassName(const tools::SvRef<SotStorage>& xStorage)
     return read_uInt8s_ToOString(*pCompObj, nData);
 }
 
+/// Parses the presentation stream of an OLE2 storage.
+bool ParseOLE2Presentation(SvStream& rOle2, sal_uInt32& nWidth, sal_uInt32& nHeight,
+                           SvStream& rPresentationData)
+{
+    // See [MS-OLEDS] 2.3.4, OLEPresentationStream
+    rOle2.Seek(0);
+    tools::SvRef<SotStorage> pStorage = new SotStorage(rOle2);
+    tools::SvRef<SotStorageStream> xOle2Presentation
+        = pStorage->OpenSotStream("\002OlePres000", StreamMode::STD_READ);
+
+    // Read AnsiClipboardFormat.
+    sal_uInt32 nMarkerOrLength = 0;
+    xOle2Presentation->ReadUInt32(nMarkerOrLength);
+    if (nMarkerOrLength != 0xffffffff)
+        // FormatOrAnsiString is not present
+        return false;
+    sal_uInt32 nFormatOrAnsiLength = 0;
+    xOle2Presentation->ReadUInt32(nFormatOrAnsiLength);
+    if (nFormatOrAnsiLength != 0x00000003) // CF_METAFILEPICT
+        return false;
+
+    // Read TargetDeviceSize.
+    sal_uInt32 nTargetDeviceSize = 0;
+    xOle2Presentation->ReadUInt32(nTargetDeviceSize);
+    if (nTargetDeviceSize != 0x00000004)
+        // TargetDevice is present
+        return false;
+
+    sal_uInt32 nAspect = 0;
+    xOle2Presentation->ReadUInt32(nAspect);
+    sal_uInt32 nLindex = 0;
+    xOle2Presentation->ReadUInt32(nLindex);
+    sal_uInt32 nAdvf = 0;
+    xOle2Presentation->ReadUInt32(nAdvf);
+    sal_uInt32 nReserved1 = 0;
+    xOle2Presentation->ReadUInt32(nReserved1);
+    xOle2Presentation->ReadUInt32(nWidth);
+    xOle2Presentation->ReadUInt32(nHeight);
+    sal_uInt32 nSize = 0;
+    xOle2Presentation->ReadUInt32(nSize);
+
+    // Read Data.
+    if (nSize > xOle2Presentation->remainingSize())
+        return false;
+    std::vector<char> aBuffer(nSize);
+    xOle2Presentation->ReadBytes(aBuffer.data(), aBuffer.size());
+    rPresentationData.WriteBytes(aBuffer.data(), aBuffer.size());
+
+    return true;
+}
+
 /// Inserts an OLE1 header before an OLE2 storage.
-OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1)
+OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1, sal_uInt32& nWidth, sal_uInt32& nHeight)
 {
     rOle2.Seek(0);
     tools::SvRef<SotStorage> xStorage(new SotStorage(rOle2));
@@ -106,7 +157,7 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1)
     // Write ObjectHeader, see [MS-OLEDS] 2.2.4.
     rOle1.Seek(0);
     // OLEVersion.
-    rOle1.WriteUInt32(0);
+    rOle1.WriteUInt32(0x00000501);
 
     // FormatID is EmbeddedObject.
     rOle1.WriteUInt32(0x00000002);
@@ -134,6 +185,35 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1)
     rOle2.Seek(0);
     rOle1.WriteStream(rOle2);
 
+    // Write Presentation.
+    SvMemoryStream aPresentationData;
+    if (ParseOLE2Presentation(rOle2, nWidth, nHeight, aPresentationData))
+    {
+        // OLEVersion.
+        rOle1.WriteUInt32(0x00000501);
+        // FormatID: constant means the ClassName field is present.
+        rOle1.WriteUInt32(0x00000005);
+        // ClassName: null terminated pascal string.
+        OString aPresentationClassName("METAFILEPICT");
+        rOle1.WriteUInt32(aPresentationClassName.getLength() + 1);
+        rOle1.WriteOString(aPresentationClassName);
+        rOle1.WriteChar(0);
+        // Width.
+        rOle1.WriteUInt32(nWidth);
+        // Height.
+        rOle1.WriteUInt32(nHeight * -1);
+        // PresentationDataSize
+        sal_uInt32 nPresentationData = aPresentationData.Tell();
+        rOle1.WriteUInt32(8 + nPresentationData);
+        // Reserved1-4.
+        rOle1.WriteUInt16(0x0008);
+        rOle1.WriteUInt16(0x31b1);
+        rOle1.WriteUInt16(0x1dd9);
+        rOle1.WriteUInt16(0x0000);
+        aPresentationData.Seek(0);
+        rOle1.WriteStream(aPresentationData);
+    }
+
     return aClassName;
 }
 
@@ -226,7 +306,9 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode)
 
     // Write OLE1 header, then the RTF wrapper.
     SvMemoryStream aOLE1;
-    OString aClassName = InsertOLE1Header(rOle2, aOLE1);
+    sal_uInt32 nWidth = 0;
+    sal_uInt32 nHeight = 0;
+    OString aClassName = InsertOLE1Header(rOle2, aOLE1, nWidth, nHeight);
 
     // Start object.
     rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_OBJECT);
@@ -239,11 +321,10 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode)
     rRtf.WriteCharPtr("}");
 
     // Object size.
-    Size aSize(rOLENode.GetTwipSize());
     rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJW);
-    rRtf.WriteCharPtr(OString::number(aSize.getWidth()).getStr());
+    rRtf.WriteCharPtr(OString::number(nWidth).getStr());
     rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJH);
-    rRtf.WriteCharPtr(OString::number(aSize.getHeight()).getStr());
+    rRtf.WriteCharPtr(OString::number(nHeight).getStr());
 
     // Start objdata.
     rRtf.WriteCharPtr(


More information about the Libreoffice-commits mailing list