1
0
Fork 0
libreoffice/sw/qa/extras/htmlexport/htmlmodeltestbase.hxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

232 lines
7.1 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <swmodeltestbase.hxx>
#include <test/htmltesttools.hxx>
#include <comphelper/propertyvalue.hxx>
#include <filter/msfilter/rtfutil.hxx>
#include <svtools/parrtf.hxx>
#include <svtools/rtftoken.h>
#include <tools/urlobj.hxx>
/// Test RTF parser that just extracts a single OLE2 object from a file.
class TestReqIfRtfReader : public SvRTFParser
{
public:
TestReqIfRtfReader(SvStream& rStream);
void NextToken(int nToken) override;
bool WriteObjectData(SvStream& rOLE);
tools::Long GetObjw() const { return m_nObjw; }
tools::Long GetObjh() const { return m_nObjh; }
int getWmetafile() const { return m_nWmetafile; }
private:
bool m_bInObjData = false;
OStringBuffer m_aHex;
tools::Long m_nObjw = 0;
tools::Long m_nObjh = 0;
int m_nWmetafile = 0;
};
TestReqIfRtfReader::TestReqIfRtfReader(SvStream& rStream)
: SvRTFParser(rStream)
{
}
void TestReqIfRtfReader::NextToken(int nToken)
{
switch (nToken)
{
case '}':
m_bInObjData = false;
break;
case RTF_TEXTTOKEN:
if (m_bInObjData)
m_aHex.append(OUStringToOString(aToken, RTL_TEXTENCODING_ASCII_US));
break;
case RTF_OBJDATA:
m_bInObjData = true;
break;
case RTF_OBJW:
m_nObjw = nTokenValue;
break;
case RTF_OBJH:
m_nObjh = nTokenValue;
break;
case RTF_WMETAFILE:
m_nWmetafile = nTokenValue;
break;
}
}
bool TestReqIfRtfReader::WriteObjectData(SvStream& rOLE)
{
OString aObjdata = m_aHex.makeStringAndClear();
SvMemoryStream aStream;
int b = 0;
int count = 2;
// Feed the destination text to a stream.
for (int i = 0; i < aObjdata.getLength(); ++i)
{
char ch = aObjdata[i];
if (ch != 0x0d && ch != 0x0a)
{
b = b << 4;
sal_Int8 parsed = msfilter::rtfutil::AsHex(ch);
if (parsed == -1)
return false;
b += parsed;
count--;
if (!count)
{
aStream.WriteChar(b);
count = 2;
b = 0;
}
}
}
aStream.Seek(0);
rOLE.WriteStream(aStream);
return true;
}
/// Parser for [MS-OLEDS] 2.2.5 EmbeddedObject, aka OLE1.
struct OLE1Reader
{
sal_uInt32 m_nNativeDataSize;
std::vector<char> m_aNativeData;
sal_uInt32 m_nPresentationDataSize;
OLE1Reader(SvStream& rStream);
};
OLE1Reader::OLE1Reader(SvStream& rStream)
{
// Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
rStream.Seek(0);
CPPUNIT_ASSERT(rStream.remainingSize());
sal_uInt32 nData;
rStream.ReadUInt32(nData); // OLEVersion
rStream.ReadUInt32(nData); // FormatID
rStream.ReadUInt32(nData); // ClassName
rStream.SeekRel(nData);
rStream.ReadUInt32(nData); // TopicName
rStream.SeekRel(nData);
rStream.ReadUInt32(nData); // ItemName
rStream.SeekRel(nData);
rStream.ReadUInt32(m_nNativeDataSize);
m_aNativeData.resize(m_nNativeDataSize);
rStream.ReadBytes(m_aNativeData.data(), m_aNativeData.size());
rStream.ReadUInt32(nData); // OLEVersion for presentation data
CPPUNIT_ASSERT(rStream.good());
rStream.ReadUInt32(nData); // FormatID
rStream.ReadUInt32(nData); // ClassName
rStream.SeekRel(nData);
rStream.ReadUInt32(nData); // Width
rStream.ReadUInt32(nData); // Height
rStream.ReadUInt32(nData); // PresentationDataSize
m_nPresentationDataSize = nData;
}
/// Covers sw/source/filter/html/wrthtml.cxx and related fixes.
class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
{
public:
HtmlExportTest()
: SwModelTestBase(u"/sw/qa/extras/htmlexport/data/"_ustr, u"HTML (StarWriter)"_ustr)
{
}
/// Wraps an RTF fragment into a complete RTF file, so an RTF parser can handle it.
static void wrapRtfFragment(const OUString& rURL, SvMemoryStream& rStream)
{
SvFileStream aRtfStream(rURL, StreamMode::READ);
rStream.WriteOString("{\\rtf1");
rStream.WriteStream(aRtfStream);
rStream.WriteOString("}");
rStream.Seek(0);
}
};
/// HTML export of the sw doc model tests.
class SwHtmlDomExportTest : public SwModelTestBase, public HtmlTestTools
{
public:
SwHtmlDomExportTest()
: SwModelTestBase(u"/sw/qa/extras/htmlexport/data/"_ustr)
{
}
OUString GetObjectPath(const OUString& ext);
/// Get the .ole path, assuming maTempFile is an XHTML export result.
OUString GetOlePath() { return GetObjectPath(u".ole"_ustr); }
OUString GetPngPath() { return GetObjectPath(u".png"_ustr); }
/// Parse the ole1 data out of an RTF fragment URL.
void ParseOle1FromRtfUrl(const OUString& rRtfUrl, SvMemoryStream& rOle1);
/// Export using the C++ HTML export filter, with xhtmlns=reqif-xhtml.
void ExportToReqif();
/// Import using the C++ HTML import filter, with xhtmlns=reqif-xhtml.
void ImportFromReqif(const OUString& rUrl);
/// Export using the C++ HTML export filter
void ExportToHTML();
};
OUString SwHtmlDomExportTest::GetObjectPath(const OUString& ext)
{
assert(ext.startsWith("."));
xmlDocUniquePtr pDoc = WrapReqifFromTempFile();
OUString aOlePath = getXPath(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object", "data");
CPPUNIT_ASSERT(aOlePath.endsWith(ext));
INetURLObject aUrl(maTempFile.GetURL());
aUrl.setBase(aOlePath.subView(0, aOlePath.getLength() - ext.getLength()));
aUrl.setExtension(ext.subView(1));
return aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE);
}
void SwHtmlDomExportTest::ParseOle1FromRtfUrl(const OUString& rRtfUrl, SvMemoryStream& rOle1)
{
SvMemoryStream aRtf;
HtmlExportTest::wrapRtfFragment(rRtfUrl, aRtf);
tools::SvRef<TestReqIfRtfReader> xReader(new TestReqIfRtfReader(aRtf));
CPPUNIT_ASSERT(xReader->CallParser() != SvParserState::Error);
CPPUNIT_ASSERT(xReader->WriteObjectData(rOle1));
CPPUNIT_ASSERT(rOle1.Tell());
}
void SwHtmlDomExportTest::ExportToReqif()
{
setFilterOptions(u"xhtmlns=reqif-xhtml"_ustr);
save(u"HTML (StarWriter)"_ustr);
}
void SwHtmlDomExportTest::ExportToHTML()
{
uno::Sequence<beans::PropertyValue> aStoreProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
};
saveWithParams(aStoreProperties);
}
void SwHtmlDomExportTest::ImportFromReqif(const OUString& rUrl)
{
uno::Sequence<beans::PropertyValue> aLoadProperties = {
comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarWriter)"_ustr),
comphelper::makePropertyValue(u"FilterOptions"_ustr, u"xhtmlns=reqif-xhtml"_ustr),
};
loadWithParams(rUrl, aLoadProperties);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */