[Libreoffice-commits] core.git: Branch 'distro/vector/vector-5.4' - 3 commits - filter/source include/filter sw/CppunitTest_sw_htmlexport.mk sw/qa sw/source
Miklos Vajna
vmiklos at collabora.co.uk
Wed Mar 28 15:23:09 UTC 2018
filter/source/msfilter/rtfutil.cxx | 32 ++++++++
include/filter/msfilter/rtfutil.hxx | 4 +
sw/CppunitTest_sw_htmlexport.mk | 37 ---------
sw/qa/extras/htmlexport/htmlexport.cxx | 22 +++++
sw/qa/extras/htmlimport/htmlimport.cxx | 17 ----
sw/source/filter/html/htmlplug.cxx | 45 ++++++++---
sw/source/filter/html/htmlreqifreader.cxx | 107 +++++++++++++++++++++++++++-
sw/source/filter/html/htmlreqifreader.hxx | 3
sw/source/filter/html/wrthtml.cxx | 20 +++++
sw/source/filter/ww8/rtfattributeoutput.cxx | 38 ---------
sw/source/filter/ww8/rtfattributeoutput.hxx | 3
sw/source/filter/ww8/rtfsdrexport.cxx | 4 -
12 files changed, 227 insertions(+), 105 deletions(-)
New commits:
commit d6d6dfca7e694a9654d6bdcc048e88804cc0884e
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Tue Mar 27 17:25:47 2018 +0200
sw HTML paste: add debug env var to capture outgoing content
Similar to existing SW_DEBUG_RTF_PASTE_TO.
Change-Id: I5d6fe72929ab6ddd3e6e175ed344781fc4e3cb31
Reviewed-on: https://gerrit.libreoffice.org/51961
Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
Tested-by: Jenkins <ci at libreoffice.org>
(cherry picked from commit af69f27e812a0e86d256e36154ecef9aaf43a32a)
diff --git a/sw/source/filter/html/wrthtml.cxx b/sw/source/filter/html/wrthtml.cxx
index 42ec9956ef9e..4db9122288b2 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -76,6 +76,8 @@
#include <IDocumentStylePoolAccess.hxx>
#include <xmloff/odffields.hxx>
#include <tools/urlobj.hxx>
+#include <osl/file.hxx>
+#include <comphelper/scopeguard.hxx>
#define MAX_INDENT_LEVEL 20
@@ -207,6 +209,24 @@ void SwHTMLWriter::SetupFilterOptions(SfxMedium& rMedium)
sal_uLong SwHTMLWriter::WriteStream()
{
+ // Intercept paste output if requested.
+ char* pPasteEnv = getenv("SW_DEBUG_HTML_PASTE_TO");
+ std::unique_ptr<SvStream> pPasteStream;
+ SvStream* pOldPasteStream = nullptr;
+ if (pPasteEnv)
+ {
+ OUString aPasteStr;
+ if (pPasteEnv
+ && osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pPasteEnv), aPasteStr)
+ == osl::FileBase::E_None)
+ {
+ pPasteStream.reset(new SvFileStream(aPasteStr, StreamMode::WRITE));
+ pOldPasteStream = &Strm();
+ SetStream(pPasteStream.get());
+ }
+ }
+ comphelper::ScopeGuard g([this, pOldPasteStream] { this->SetStream(pOldPasteStream); });
+
SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
// font heights 1-7
commit b5d51f341c7e1162062ac6adf193edddab2e71c5
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Tue Mar 27 12:06:25 2018 +0200
msfilter: extract duplicated WriteHex() from HTML/RTF filter
The RtfAttributeOutput one is a superset of the HTML one, so use that.
Reviewed-on: https://gerrit.libreoffice.org/51937
Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
Tested-by: Jenkins <ci at libreoffice.org>
(cherry picked from commit 6d05579c7fceb0f3ce83abe25bdfe62b26c29671)
Conflicts:
sw/source/filter/ww8/rtfattributeoutput.cxx
sw/source/filter/ww8/rtfattributeoutput.hxx
sw/source/filter/ww8/rtfsdrexport.cxx
Change-Id: I3e342113a7ba26946320f43a164e457d6cbb6946
diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx
index b209f70a3a3c..57f7ca7ff14b 100644
--- a/filter/source/msfilter/rtfutil.cxx
+++ b/filter/source/msfilter/rtfutil.cxx
@@ -201,6 +201,38 @@ int AsHex(char ch)
return ret;
}
+OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, SvStream* pStream, sal_uInt32 nLimit)
+{
+ OStringBuffer aRet;
+
+ sal_uInt32 nBreak = 0;
+ for (sal_uInt32 i = 0; i < nSize; i++)
+ {
+ OString sNo = OString::number(pData[i], 16);
+ if (sNo.getLength() < 2)
+ {
+ if (pStream)
+ pStream->WriteChar('0');
+ else
+ aRet.append('0');
+ }
+ if (pStream)
+ pStream->WriteCharPtr(sNo.getStr());
+ else
+ aRet.append(sNo);
+ if (++nBreak == nLimit)
+ {
+ if (pStream)
+ pStream->WriteCharPtr(SAL_NEWLINE_STRING);
+ else
+ aRet.append(SAL_NEWLINE_STRING);
+ nBreak = 0;
+ }
+ }
+
+ return aRet.makeStringAndClear();
+}
+
bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
{
SvMemoryStream aStream;
diff --git a/include/filter/msfilter/rtfutil.hxx b/include/filter/msfilter/rtfutil.hxx
index 18c38adf7842..f4699169143a 100644
--- a/include/filter/msfilter/rtfutil.hxx
+++ b/include/filter/msfilter/rtfutil.hxx
@@ -58,6 +58,10 @@ MSFILTER_DLLPUBLIC OString OutStringUpr(const sal_Char *pToken, const OUString &
*/
MSFILTER_DLLPUBLIC int AsHex(char ch);
+/// Writes binary data as a hex dump.
+MSFILTER_DLLPUBLIC OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize,
+ SvStream* pStream = nullptr, sal_uInt32 nLimit = 64);
+
/**
* Extract OLE2 data from an \objdata hex dump.
*/
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index 2a4519119e31..077483ab158b 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -130,30 +130,6 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1)
return aClassName;
}
-
-/// Writes rData on rSteram as a hexdump.
-void WriteHex(SvStream& rStream, SvMemoryStream& rData)
-{
- rData.Seek(0);
- sal_uInt64 nSize = rData.remainingSize();
-
- sal_uInt32 nLimit = 64;
- sal_uInt32 nBreak = 0;
-
- for (sal_uInt64 i = 0; i < nSize; i++)
- {
- OString sNo = OString::number(static_cast<const sal_uInt8*>(rData.GetBuffer())[i], 16);
- if (sNo.getLength() < 2)
- rStream.WriteChar('0');
- rStream.WriteCharPtr(sNo.getStr());
-
- if (++nBreak == nLimit)
- {
- rStream.WriteCharPtr(SAL_NEWLINE_STRING);
- nBreak = 0;
- }
- }
-}
}
namespace SwReqIfReader
@@ -199,7 +175,8 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf)
// Start objdata.
rRtf.WriteCharPtr(
"{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA SAL_NEWLINE_STRING);
- WriteHex(rRtf, aOLE1);
+ msfilter::rtfutil::WriteHex(static_cast<const sal_uInt8*>(aOLE1.GetData()), aOLE1.GetSize(),
+ &rRtf);
// End objdata.
rRtf.WriteCharPtr("}");
// End object.
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 5aedd6721559..134eb1735d69 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -3681,38 +3681,6 @@ static bool StripMetafileHeader(const sal_uInt8*& rpGraphicAry, unsigned long& r
return false;
}
-OString RtfAttributeOutput::WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, SvStream* pStream, sal_uInt32 nLimit)
-{
- OStringBuffer aRet;
-
- sal_uInt32 nBreak = 0;
- for (sal_uInt32 i = 0; i < nSize; i++)
- {
- OString sNo = OString::number(pData[i], 16);
- if (sNo.getLength() < 2)
- {
- if (pStream)
- pStream->WriteChar('0');
- else
- aRet.append('0');
- }
- if (pStream)
- pStream->WriteCharPtr(sNo.getStr());
- else
- aRet.append(sNo);
- if (++nBreak == nLimit)
- {
- if (pStream)
- pStream->WriteCharPtr(SAL_NEWLINE_STRING);
- else
- aRet.append(SAL_NEWLINE_STRING);
- nBreak = 0;
- }
- }
-
- return aRet.makeStringAndClear();
-}
-
static void lcl_AppendSP(OStringBuffer& rBuffer,
const char cName[],
const OUString& rValue,
@@ -3795,9 +3763,9 @@ static OString ExportPICT(const SwFlyFrameFormat* pFlyFrameFormat, const Size& r
if (pStream)
pStream->WriteCharPtr(aRet.makeStringAndClear().getStr());
if (pStream)
- RtfAttributeOutput::WriteHex(pGraphicAry, nSize, pStream);
+ msfilter::rtfutil::WriteHex(pGraphicAry, nSize, pStream);
else
- aRet.append(RtfAttributeOutput::WriteHex(pGraphicAry, nSize));
+ aRet.append(msfilter::rtfutil::WriteHex(pGraphicAry, nSize));
aRet.append('}');
if (pStream)
pStream->WriteCharPtr(aRet.makeStringAndClear().getStr());
@@ -4090,7 +4058,7 @@ void RtfAttributeOutput::BulletDefinition(int /*nId*/, const Graphic& rGraphic,
aStream.Seek(STREAM_SEEK_TO_END);
sal_uInt32 nSize = aStream.Tell();
pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
- RtfAttributeOutput::WriteHex(pGraphicAry, nSize, &m_rExport.Strm());
+ msfilter::rtfutil::WriteHex(pGraphicAry, nSize, &m_rExport.Strm());
m_rExport.Strm().WriteCharPtr("}}"); // pict, shppict
}
diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx
index 23e8466681da..1d2027433c95 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.hxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -636,9 +636,6 @@ public:
/// Font pitch.
void FontPitchType(FontPitch ePitch) const;
- /// Writes binary data as a hex dump.
- static OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, SvStream* pStream = nullptr, sal_uInt32 nLimit = 64);
-
void BulletDefinition(int nId, const Graphic& rGraphic, Size aSize) override;
/// Handles just the {\shptxt ...} part of a shape export.
diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx
index cb5f2c1a90c5..af01b408ac03 100644
--- a/sw/source/filter/ww8/rtfsdrexport.cxx
+++ b/sw/source/filter/ww8/rtfsdrexport.cxx
@@ -393,7 +393,7 @@ void RtfSdrExport::Commit(EscherPropertyContainer& rProps, const tools::Rectangl
OStringBuffer aBuf;
aBuf.append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP).append(SAL_NEWLINE_STRING);
int nHeaderSize = 25; // The first bytes are WW8-specific, we're only interested in the PNG
- aBuf.append(RtfAttributeOutput::WriteHex(rOpt.pBuf + nHeaderSize, rOpt.nPropSize - nHeaderSize));
+ aBuf.append(msfilter::rtfutil::WriteHex(rOpt.pBuf + nHeaderSize, rOpt.nPropSize - nHeaderSize));
aBuf.append('}');
m_aShapeProps.insert(std::pair<OString,OString>("fillBlip", aBuf.makeStringAndClear()));
}
@@ -485,7 +485,7 @@ void RtfSdrExport::impl_writeGraphic()
aBuf->append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP);
aBuf->append(OOO_STRING_SVTOOLS_RTF_PICW).append(sal_Int32(aMapped.Width()));
aBuf->append(OOO_STRING_SVTOOLS_RTF_PICH).append(sal_Int32(aMapped.Height())).append(SAL_NEWLINE_STRING);
- aBuf->append(RtfAttributeOutput::WriteHex(pGraphicAry, nSize));
+ aBuf->append(msfilter::rtfutil::WriteHex(pGraphicAry, nSize));
aBuf->append('}');
m_aShapeProps.insert(std::pair<OString,OString>("pib", aBuf.makeStringAndClear()));
}
commit 743ce5979124d28ee10a566f1462dbb67c8cd5af
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Mon Mar 26 16:25:06 2018 +0200
sw XHTML export: support OLE2-in-RTF objects
Need to repeat what OLE1 calls the class name in the OLE1 and RTF
wrappers, so parse our own OLE2 data during export.
Reviewed-on: https://gerrit.libreoffice.org/51906
Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
Tested-by: Jenkins <ci at libreoffice.org>
(cherry picked from commit 04630f26d06c4d3ec22b2a8b97e6a5e69cc70d5e)
Conflicts:
sw/CppunitTest_sw_htmlexport.mk
Change-Id: Ic14fa648d1f78c29579bd9ba49ce6f491d4541b5
diff --git a/sw/CppunitTest_sw_htmlexport.mk b/sw/CppunitTest_sw_htmlexport.mk
index c9934c5b5bf9..4dabbe61606f 100644
--- a/sw/CppunitTest_sw_htmlexport.mk
+++ b/sw/CppunitTest_sw_htmlexport.mk
@@ -48,42 +48,7 @@ $(eval $(call gb_CppunitTest_use_sdk_api,sw_htmlexport))
$(eval $(call gb_CppunitTest_use_ure,sw_htmlexport))
$(eval $(call gb_CppunitTest_use_vcl,sw_htmlexport))
-$(eval $(call gb_CppunitTest_use_components,sw_htmlexport,\
- basic/util/sb \
- canvas/source/factory/canvasfactory \
- comphelper/util/comphelp \
- configmgr/source/configmgr \
- dbaccess/util/dba \
- embeddedobj/util/embobj \
- filter/source/config/cache/filterconfig1 \
- filter/source/storagefilterdetect/storagefd \
- filter/source/textfilterdetect/textfd \
- forms/util/frm \
- framework/util/fwk \
- i18npool/util/i18npool \
- linguistic/source/lng \
- oox/util/oox \
- package/source/xstor/xstor \
- sc/util/sc \
- sc/util/scfilt \
- package/util/package2 \
- sax/source/expatwrap/expwrap \
- sw/util/sw \
- sw/util/swd \
- sw/util/msword \
- sfx2/util/sfx \
- starmath/util/sm \
- svl/source/fsstor/fsstorage \
- svtools/util/svt \
- toolkit/util/tk \
- ucb/source/core/ucb1 \
- ucb/source/ucp/file/ucpfile1 \
- unotools/util/utl \
- unoxml/source/service/unoxml \
- uui/util/uui \
- writerfilter/util/writerfilter \
- xmloff/util/xo \
-))
+$(eval $(call gb_CppunitTest_use_rdb,sw_htmlexport,services))
$(eval $(call gb_CppunitTest_use_configuration,sw_htmlexport))
diff --git a/sw/qa/extras/htmlimport/data/ole2.ole b/sw/qa/extras/htmlexport/data/ole2.ole
similarity index 100%
rename from sw/qa/extras/htmlimport/data/ole2.ole
rename to sw/qa/extras/htmlexport/data/ole2.ole
diff --git a/sw/qa/extras/htmlimport/data/ole2.png b/sw/qa/extras/htmlexport/data/ole2.png
similarity index 100%
rename from sw/qa/extras/htmlimport/data/ole2.png
rename to sw/qa/extras/htmlexport/data/ole2.png
diff --git a/sw/qa/extras/htmlimport/data/reqif-ole2.xhtml b/sw/qa/extras/htmlexport/data/reqif-ole2.xhtml
similarity index 100%
rename from sw/qa/extras/htmlimport/data/reqif-ole2.xhtml
rename to sw/qa/extras/htmlexport/data/reqif-ole2.xhtml
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 0cac2dad965c..8072e530859d 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -14,6 +14,8 @@
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
#include <rtl/byteseq.hxx>
#include <swmodule.hxx>
@@ -476,6 +478,26 @@ DECLARE_HTMLEXPORT_TEST(testReqIfTable, "reqif-table.xhtml")
assertXPathNoAttribute(pDoc, "/html/body/div/table/tr/th", "bgcolor");
}
+DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfOle2, "reqif-ole2.xhtml")
+{
+ uno::Reference<text::XTextEmbeddedObjectsSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xObjects(xSupplier->getEmbeddedObjects(),
+ uno::UNO_QUERY);
+ uno::Reference<document::XEmbeddedObjectSupplier2> xObject(xObjects->getByIndex(0),
+ uno::UNO_QUERY);
+ uno::Reference<io::XActiveDataStreamer> xEmbeddedObject(xObject->getExtendedControlOverEmbeddedObject(), uno::UNO_QUERY);
+ // This failed, the "RTF fragment" native data was loaded as-is, we had no
+ // 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.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(38912), 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.
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/htmlimport/htmlimport.cxx b/sw/qa/extras/htmlimport/htmlimport.cxx
index 9c5e2ce63aa8..02e2417a2b0e 100644
--- a/sw/qa/extras/htmlimport/htmlimport.cxx
+++ b/sw/qa/extras/htmlimport/htmlimport.cxx
@@ -251,23 +251,6 @@ DECLARE_HTMLIMPORT_TEST(testReqIfBr, "reqif-br.xhtml")
CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("aaa\nbbb"));
}
-DECLARE_HTMLIMPORT_TEST(testReqIfOle2, "reqif-ole2.xhtml")
-{
- uno::Reference<text::XTextEmbeddedObjectsSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
- uno::Reference<container::XIndexAccess> xObjects(xSupplier->getEmbeddedObjects(),
- uno::UNO_QUERY);
- uno::Reference<document::XEmbeddedObjectSupplier2> xObject(xObjects->getByIndex(0),
- uno::UNO_QUERY);
- uno::Reference<io::XActiveDataStreamer> xEmbeddedObject(xObject->getExtendedControlOverEmbeddedObject(), uno::UNO_QUERY);
- // This failed, the "RTF fragment" native data was loaded as-is, we had no
- // 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.
- CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(38912), xStream->getLength());
-}
-
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx
index 8ffc189d3446..68ad0c0be432 100644
--- a/sw/source/filter/html/htmlplug.cxx
+++ b/sw/source/filter/html/htmlplug.cxx
@@ -61,12 +61,14 @@
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <comphelper/classids.hxx>
#include <rtl/uri.hxx>
#include <comphelper/storagehelper.hxx>
#include <vcl/graphicfilter.hxx>
+#include <unotools/ucbstreamhelper.hxx>
using namespace com::sun::star;
@@ -1453,19 +1455,40 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame
aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
// Write the data.
- OUString aStreamName = pOLENd->GetOLEObj().GetCurrentPersistName();
- uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
- uno::Reference<io::XStream> xInStream
- = xStorage->openStreamElement(aStreamName, embed::ElementModes::READ);
+ SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
+ uno::Reference<embed::XEmbeddedObject> xEmbeddedObject = rOLEObj.GetOleRef();
+ OUString aFileType;
SvFileStream aOutStream(aFileName, StreamMode::WRITE);
- uno::Reference<io::XStream> xOutStream(new utl::OStreamWrapper(aOutStream));
- comphelper::OStorageHelper::CopyInputToOutput(xInStream->getInputStream(),
- xOutStream->getOutputStream());
+ uno::Reference<io::XActiveDataStreamer> xStreamProvider;
+ if (xEmbeddedObject.is())
+ xStreamProvider.set(xEmbeddedObject, uno::UNO_QUERY);
+ if (xStreamProvider.is())
+ {
+ uno::Reference<io::XInputStream> xStream(xStreamProvider->getStream(), uno::UNO_QUERY);
+ if (xStream.is())
+ {
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xStream));
+ if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream))
+ {
+ // OLE2 is always wrapped in RTF.
+ aFileType = "text/rtf";
+ }
+ }
+ }
+ else
+ {
+ OUString aStreamName = rOLEObj.GetCurrentPersistName();
+ uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
+ uno::Reference<io::XStream> xInStream
+ = xStorage->openStreamElement(aStreamName, embed::ElementModes::READ);
+ uno::Reference<io::XStream> xOutStream(new utl::OStreamWrapper(aOutStream));
+ comphelper::OStorageHelper::CopyInputToOutput(xInStream->getInputStream(),
+ xOutStream->getOutputStream());
+ uno::Reference<beans::XPropertySet> xOutStreamProps(xInStream, uno::UNO_QUERY);
+ if (xOutStreamProps.is())
+ xOutStreamProps->getPropertyValue("MediaType") >>= aFileType;
+ }
aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName);
- uno::Reference<beans::XPropertySet> xOutStreamProps(xInStream, uno::UNO_QUERY);
- OUString aFileType;
- if (xOutStreamProps.is())
- xOutStreamProps->getPropertyValue("MediaType") >>= aFileType;
// Refer to this data.
if (rHTMLWrt.m_bLFPossible)
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index eef33d93b293..2a4519119e31 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -9,12 +9,15 @@
#include "htmlreqifreader.hxx"
+#include <comphelper/scopeguard.hxx>
+#include <filter/msfilter/rtfutil.hxx>
#include <rtl/character.hxx>
#include <rtl/strbuf.hxx>
+#include <sot/storage.hxx>
#include <svtools/parrtf.hxx>
+#include <svtools/rtfkeywd.hxx>
#include <svtools/rtftoken.h>
#include <tools/stream.hxx>
-#include <filter/msfilter/rtfutil.hxx>
namespace
{
@@ -57,6 +60,100 @@ bool ReqIfRtfReader::WriteObjectData(SvStream& rOLE)
{
return msfilter::rtfutil::ExtractOLE2FromObjdata(m_aHex.makeStringAndClear(), rOLE);
}
+
+/// Looks up what OLE1 calls the ClassName, see [MS-OLEDS] 2.3.8 CompObjStream.
+OString ExtractOLEClassName(const tools::SvRef<SotStorage>& xStorage)
+{
+ OString aRet;
+
+ SotStorageStream* pCompObj = xStorage->OpenSotStream("\1CompObj");
+ if (!pCompObj)
+ return aRet;
+
+ pCompObj->Seek(0);
+ pCompObj->SeekRel(28); // Header
+ if (!pCompObj->good())
+ return aRet;
+
+ sal_uInt32 nData;
+ pCompObj->ReadUInt32(nData); // AnsiUserType
+ pCompObj->SeekRel(nData);
+ if (!pCompObj->good())
+ return aRet;
+
+ pCompObj->ReadUInt32(nData); // AnsiClipboardFormat
+ pCompObj->SeekRel(nData);
+ if (!pCompObj->good())
+ return aRet;
+
+ pCompObj->ReadUInt32(nData); // Reserved1
+ return read_uInt8s_ToOString(*pCompObj, nData);
+}
+
+/// Inserts an OLE1 header before an OLE2 storage.
+OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1)
+{
+ rOle2.Seek(0);
+ tools::SvRef<SotStorage> xStorage(new SotStorage(rOle2));
+ if (xStorage->GetError() != ERRCODE_NONE)
+ return OString();
+
+ OString aClassName = ExtractOLEClassName(xStorage);
+
+ // Write ObjectHeader, see [MS-OLEDS] 2.2.4.
+ rOle1.Seek(0);
+ // OLEVersion.
+ rOle1.WriteUInt32(0);
+
+ // FormatID is EmbeddedObject.
+ rOle1.WriteUInt32(0x00000002);
+
+ // ClassName
+ rOle1.WriteUInt32(aClassName.getLength());
+ rOle1.WriteOString(aClassName);
+ // Null terminated pascal string.
+ rOle1.WriteChar(0);
+
+ // TopicName.
+ rOle1.WriteUInt32(0);
+
+ // ItemName.
+ rOle1.WriteUInt32(0);
+
+ // NativeDataSize
+ rOle2.Seek(STREAM_SEEK_TO_END);
+ rOle1.WriteUInt32(rOle2.Tell());
+
+ // Write the actual native data.
+ rOle2.Seek(0);
+ rOle1.WriteStream(rOle2);
+
+ return aClassName;
+}
+
+/// Writes rData on rSteram as a hexdump.
+void WriteHex(SvStream& rStream, SvMemoryStream& rData)
+{
+ rData.Seek(0);
+ sal_uInt64 nSize = rData.remainingSize();
+
+ sal_uInt32 nLimit = 64;
+ sal_uInt32 nBreak = 0;
+
+ for (sal_uInt64 i = 0; i < nSize; i++)
+ {
+ OString sNo = OString::number(static_cast<const sal_uInt8*>(rData.GetBuffer())[i], 16);
+ if (sNo.getLength() < 2)
+ rStream.WriteChar('0');
+ rStream.WriteCharPtr(sNo.getStr());
+
+ if (++nBreak == nLimit)
+ {
+ rStream.WriteCharPtr(SAL_NEWLINE_STRING);
+ nBreak = 0;
+ }
+ }
+}
}
namespace SwReqIfReader
@@ -79,6 +176,37 @@ bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle)
// Write the OLE2 data.
return xReader->WriteObjectData(rOle);
}
+
+bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf)
+{
+ sal_uInt64 nPos = rOle2.Tell();
+ comphelper::ScopeGuard g([&rOle2, nPos] { rOle2.Seek(nPos); });
+
+ // Write OLE1 header, then the RTF wrapper.
+ SvMemoryStream aOLE1;
+ OString aClassName = InsertOLE1Header(rOle2, aOLE1);
+
+ // Start object.
+ rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_OBJECT);
+ rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJEMB);
+
+ // Start objclass.
+ rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJCLASS " ");
+ rRtf.WriteOString(aClassName);
+ // End objclass.
+ rRtf.WriteCharPtr("}");
+
+ // Start objdata.
+ rRtf.WriteCharPtr(
+ "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA SAL_NEWLINE_STRING);
+ WriteHex(rRtf, aOLE1);
+ // End objdata.
+ rRtf.WriteCharPtr("}");
+ // End object.
+ rRtf.WriteCharPtr("}");
+
+ return true;
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlreqifreader.hxx b/sw/source/filter/html/htmlreqifreader.hxx
index 97d391a8efb0..ad8399edbf0e 100644
--- a/sw/source/filter/html/htmlreqifreader.hxx
+++ b/sw/source/filter/html/htmlreqifreader.hxx
@@ -15,6 +15,9 @@ namespace SwReqIfReader
{
/// Extracts an OLE2 container binary from an RTF fragment.
bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle);
+
+/// Wraps an OLE2 container binary in an RTF fragment.
+bool WrapOleInRtf(SvStream& rOle, SvStream& rRtf);
}
#endif // INCLUDED_SW_SOURCE_FILTER_HTML_HTMLREQIFREADER_HXX
More information about the Libreoffice-commits
mailing list