summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2015-04-16 14:22:05 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2015-04-16 15:32:26 +0200
commit2a3e8b470edf2fe76188f9ccf6b0f32dfc817ea4 (patch)
tree77821561f8bfedcbe21585f124fe8c81cdbde552 /writerfilter
parente7df7c098ed3a6dc1ecf5b20857835d16d1f9283 (diff)
RTF import: fix handling of \objdata
There were two problems here: 1) The input stream is read multiple times, so plain naive XInputStream is not enough, XSeekable is needed, as it is the case for the stream provided by the OOXML tokenizer. 2) Seeking to the correct start position is not enough, code using the stream will assume that seeking to the beginning of the stream allows reading the correct data again, so provide a dedicated stream instead. With this, handling of math equations created by Word <= 2007 and embedded to RTF files can be edited finally. Change-Id: Ic225e1e1060f8bdd5651a21e68970620c9ac6b68
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx108
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx2
2 files changed, 63 insertions, 47 deletions
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index c74399c79090..d00662375dfc 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -5349,53 +5349,9 @@ RTFError RTFDocumentImpl::popState()
if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
break; // not for nested group
- m_pObjectData.reset(new SvMemoryStream());
- int b = 0, count = 2;
-
- // Feed the destination text to a stream.
- OString aStr = OUStringToOString(m_aStates.top().pDestinationText->makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
- const char* str = aStr.getStr();
- for (int i = 0; i < aStr.getLength(); ++i)
- {
- char ch = str[i];
- if (ch != 0x0d && ch != 0x0a)
- {
- b = b << 4;
- sal_Int8 parsed = m_pTokenizer->asHex(ch);
- if (parsed == -1)
- return RTFError::HEX_INVALID;
- b += parsed;
- count--;
- if (!count)
- {
- m_pObjectData->WriteChar((char)b);
- count = 2;
- b = 0;
- }
- }
- }
-
- if (m_pObjectData->Tell())
- {
- m_pObjectData->Seek(0);
-
- // Skip ObjectHeader
- sal_uInt32 nData;
- m_pObjectData->ReadUInt32(nData); // OLEVersion
- m_pObjectData->ReadUInt32(nData); // FormatID
- m_pObjectData->ReadUInt32(nData); // ClassName
- m_pObjectData->SeekRel(nData);
- m_pObjectData->ReadUInt32(nData); // TopicName
- m_pObjectData->SeekRel(nData);
- m_pObjectData->ReadUInt32(nData); // ItemName
- m_pObjectData->SeekRel(nData);
- m_pObjectData->ReadUInt32(nData); // NativeDataSize
- }
-
- uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(m_pObjectData.get()));
- auto pStreamValue = std::make_shared<RTFValue>(xInputStream);
-
- m_aOLEAttributes.set(NS_ooxml::LN_inputstream, pStreamValue);
+ RTFError eError = handleEmbeddedObject();
+ if (eError != RTFError::OK)
+ return eError;
}
break;
case Destination::OBJCLASS:
@@ -6058,6 +6014,64 @@ RTFError RTFDocumentImpl::popState()
return RTFError::OK;
}
+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);
+ const char* str = aStr.getStr();
+ for (int i = 0; i < aStr.getLength(); ++i)
+ {
+ char ch = str[i];
+ if (ch != 0x0d && ch != 0x0a)
+ {
+ b = b << 4;
+ sal_Int8 parsed = m_pTokenizer->asHex(ch);
+ if (parsed == -1)
+ return RTFError::HEX_INVALID;
+ 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)
+ {
+ m_pObjectData.reset(new SvMemoryStream());
+ m_pObjectData->WriteStream(aStream);
+ m_pObjectData->Seek(0);
+ }
+ }
+
+ uno::Reference<io::XInputStream> xInputStream(new utl::OSeekableInputStreamWrapper(m_pObjectData.get()));
+ auto pStreamValue = std::make_shared<RTFValue>(xInputStream);
+ m_aOLEAttributes.set(NS_ooxml::LN_inputstream, pStreamValue);
+
+ return RTFError::OK;
+}
+
bool RTFDocumentImpl::isInBackground()
{
return m_aStates.top().bInBackground;
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 7112c5833eb6..0af39d3ae98a 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -439,6 +439,8 @@ private:
void resetTableRowProperties();
void backupTableRowProperties();
void restoreTableRowProperties();
+ /// Turns the destination text into an input stream of the current OLE attributes.
+ RTFError handleEmbeddedObject();
css::uno::Reference<css::uno::XComponentContext> const& m_xContext;
css::uno::Reference<css::io::XInputStream> const& m_xInputStream;