Kaydet (Commit) 679a3b93 authored tarafından Miklos Vajna's avatar Miklos Vajna

msfilter: extract copy&pasted RTF code from sw and writerfilter

Both the hexdump and the OLE1 reader can be shared.

Change-Id: I97d72a8deeb9c79fc8e8c4a73c613213badfa744
Reviewed-on: https://gerrit.libreoffice.org/51783Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: 's avatarJenkins <ci@libreoffice.org>
üst 1ed1753b
......@@ -11,6 +11,9 @@
#include <rtl/strbuf.hxx>
#include <osl/diagnose.h>
#include <svtools/rtfkeywd.hxx>
#include <rtl/character.hxx>
#include <tools/stream.hxx>
#include <unotools/streamwrap.hxx>
namespace msfilter
{
......@@ -182,6 +185,75 @@ OString OutStringUpr(const sal_Char* pToken, const OUString& rStr, rtl_TextEncod
aRet.append("}}}");
return aRet.makeStringAndClear();
}
int AsHex(char ch)
{
int ret = 0;
if (rtl::isAsciiDigit(static_cast<unsigned char>(ch)))
ret = ch - '0';
else
{
if (ch >= 'a' && ch <= 'f')
ret = ch - 'a';
else if (ch >= 'A' && ch <= 'F')
ret = ch - 'A';
else
return -1;
ret += 10;
}
return ret;
}
bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
{
SvMemoryStream aStream;
int b = 0, count = 2;
// Feed the destination text to a stream.
for (int i = 0; i < rObjdata.getLength(); ++i)
{
char ch = rObjdata[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;
}
}
}
// Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
if (aStream.Tell())
{
aStream.Seek(0);
sal_uInt32 nData;
aStream.ReadUInt32(nData); // OLEVersion
aStream.ReadUInt32(nData); // FormatID
aStream.ReadUInt32(nData); // ClassName
aStream.SeekRel(nData);
aStream.ReadUInt32(nData); // TopicName
aStream.SeekRel(nData);
aStream.ReadUInt32(nData); // ItemName
aStream.SeekRel(nData);
aStream.ReadUInt32(nData); // NativeDataSize
if (nData)
{
rOle2.WriteStream(aStream);
rOle2.Seek(0);
}
}
return true;
}
}
}
......
......@@ -20,6 +20,8 @@
// RTF values are often multiplied by 2^16
#define RTF_MULTIPLIER 65536
class SvStream;
namespace msfilter
{
namespace rtfutil
......@@ -52,6 +54,18 @@ MSFILTER_DLLPUBLIC OString OutString(const OUString& rStr, rtl_TextEncoding eDes
*/
MSFILTER_DLLPUBLIC OString OutStringUpr(const sal_Char* pToken, const OUString& rStr,
rtl_TextEncoding eDestEnc);
/**
* Get the numeric value of a single character, representing a hex value.
*
* @return -1 on failure
*/
MSFILTER_DLLPUBLIC int AsHex(char ch);
/**
* Extract OLE2 data from an \objdata hex dump.
*/
MSFILTER_DLLPUBLIC bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2);
}
}
......
......@@ -35,6 +35,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_uwriter, \
i18nlangtag \
i18nutil \
lng \
msfilter \
oox \
sal \
salhelper \
......
......@@ -59,6 +59,7 @@ $(eval $(call gb_Library_use_libraries,sw,\
i18nlangtag \
i18nutil \
lng \
msfilter \
sal \
salhelper \
sax \
......
......@@ -14,27 +14,10 @@
#include <svtools/parrtf.hxx>
#include <svtools/rtftoken.h>
#include <tools/stream.hxx>
#include <filter/msfilter/rtfutil.hxx>
namespace
{
int AsHex(char ch)
{
int ret = 0;
if (rtl::isAsciiDigit(static_cast<unsigned char>(ch)))
ret = ch - '0';
else
{
if (ch >= 'a' && ch <= 'f')
ret = ch - 'a';
else if (ch >= 'A' && ch <= 'F')
ret = ch - 'A';
else
return -1;
ret += 10;
}
return ret;
}
/// RTF parser that just extracts a single OLE2 object from a file.
class ReqIfRtfReader : public SvRTFParser
{
......@@ -72,52 +55,7 @@ void ReqIfRtfReader::NextToken(int nToken)
bool ReqIfRtfReader::WriteObjectData(SvStream& rOLE)
{
int b = 0, count = 2;
SvMemoryStream aBuf;
for (int i = 0; i < m_aHex.getLength(); ++i)
{
char ch = m_aHex[i];
if (ch != 0x0d && ch != 0x0a)
{
b = b << 4;
sal_Int8 parsed = AsHex(ch);
if (parsed == -1)
return false;
b += parsed;
count--;
if (!count)
{
aBuf.WriteChar(b);
count = 2;
b = 0;
}
}
}
// Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
if (aBuf.Tell())
{
aBuf.Seek(0);
sal_uInt32 nData;
aBuf.ReadUInt32(nData); // OLEVersion
aBuf.ReadUInt32(nData); // FormatID
aBuf.ReadUInt32(nData); // ClassName
aBuf.SeekRel(nData);
aBuf.ReadUInt32(nData); // TopicName
aBuf.SeekRel(nData);
aBuf.ReadUInt32(nData); // ItemName
aBuf.SeekRel(nData);
aBuf.ReadUInt32(nData); // NativeDataSize
if (nData)
{
rOLE.WriteStream(aBuf);
rOLE.Seek(0);
}
}
return true;
return msfilter::rtfutil::ExtractOLE2FromObjdata(m_aHex.makeStringAndClear(), rOLE);
}
}
......
......@@ -19,6 +19,7 @@
#include <unotools/streamwrap.hxx>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <filter/msfilter/util.hxx>
#include <filter/msfilter/rtfutil.hxx>
#include <comphelper/string.hxx>
#include <vcl/GraphicObject.hxx>
#include <tools/globname.hxx>
......@@ -816,7 +817,7 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
if (ch != 0x0d && ch != 0x0a && ch != 0x20)
{
b = b << 4;
sal_Int8 parsed = RTFTokenizer::asHex(ch);
sal_Int8 parsed = msfilter::rtfutil::AsHex(ch);
if (parsed == -1)
return;
b += parsed;
......@@ -2342,7 +2343,7 @@ RTFError RTFDocumentImpl::popState()
if (ch != 0x0d && ch != 0x0a)
{
b = b << 4;
sal_Int8 parsed = RTFTokenizer::asHex(ch);
sal_Int8 parsed = msfilter::rtfutil::AsHex(ch);
if (parsed == -1)
return RTFError::HEX_INVALID;
b += parsed;
......@@ -3319,55 +3320,11 @@ RTFError RTFDocumentImpl::popState()
RTFError RTFDocumentImpl::handleEmbeddedObject()
{
SvMemoryStream aStream;
int b = 0, count = 2;
// Feed the destination text to a stream.
OString aStr = OUStringToOString(m_aStates.top().pDestinationText->makeStringAndClear(),
RTL_TEXTENCODING_ASCII_US);
for (int i = 0; i < aStr.getLength(); ++i)
{
char ch = aStr[i];
if (ch != 0x0d && ch != 0x0a)
{
b = b << 4;
sal_Int8 parsed = RTFTokenizer::asHex(ch);
if (parsed == -1)
return RTFError::HEX_INVALID;
b += parsed;
count--;
if (!count)
{
aStream.WriteChar(b);
count = 2;
b = 0;
}
}
}
std::unique_ptr<SvStream> pStream(new SvMemoryStream());
// Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
if (aStream.Tell())
{
aStream.Seek(0);
sal_uInt32 nData;
aStream.ReadUInt32(nData); // OLEVersion
aStream.ReadUInt32(nData); // FormatID
aStream.ReadUInt32(nData); // ClassName
aStream.SeekRel(nData);
aStream.ReadUInt32(nData); // TopicName
aStream.SeekRel(nData);
aStream.ReadUInt32(nData); // ItemName
aStream.SeekRel(nData);
aStream.ReadUInt32(nData); // NativeDataSize
if (nData)
{
pStream->WriteStream(aStream);
pStream->Seek(0);
}
}
if (!msfilter::rtfutil::ExtractOLE2FromObjdata(aStr, *pStream))
return RTFError::HEX_INVALID;
uno::Reference<io::XInputStream> xInputStream(
new utl::OSeekableInputStreamWrapper(pStream.release(), /*_bOwner=*/true));
......
......@@ -17,6 +17,7 @@
#include "rtfskipdestination.hxx"
#include <com/sun/star/io/BufferSizeExceededException.hpp>
#include <osl/diagnose.h>
#include <filter/msfilter/rtfutil.hxx>
using namespace com::sun::star;
......@@ -140,7 +141,7 @@ RTFError RTFTokenizer::resolveParse()
{
SAL_INFO("writerfilter.rtf", OSL_THIS_FUNC << ": hex internal state");
b = b << 4;
sal_Int8 parsed = asHex(ch);
sal_Int8 parsed = msfilter::rtfutil::AsHex(ch);
if (parsed == -1)
return RTFError::HEX_INVALID;
b += parsed;
......@@ -167,24 +168,6 @@ RTFError RTFTokenizer::resolveParse()
return RTFError::OK;
}
int RTFTokenizer::asHex(char ch)
{
int ret = 0;
if (rtl::isAsciiDigit(static_cast<unsigned char>(ch)))
ret = ch - '0';
else
{
if (ch >= 'a' && ch <= 'f')
ret = ch - 'a';
else if (ch >= 'A' && ch <= 'F')
ret = ch - 'A';
else
return -1;
ret += 10;
}
return ret;
}
void RTFTokenizer::pushGroup() { m_nGroup++; }
void RTFTokenizer::popGroup() { m_nGroup--; }
......
......@@ -31,7 +31,6 @@ public:
~RTFTokenizer();
RTFError resolveParse();
static int asHex(char ch);
/// Number of states on the stack.
int getGroup() const { return m_nGroup; }
/// To be invoked by the pushState() callback to signal when the importer enters a group.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment