From 2a3e8b470edf2fe76188f9ccf6b0f32dfc817ea4 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Thu, 16 Apr 2015 14:22:05 +0200 Subject: 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 --- sw/qa/extras/rtfimport/data/mathtype.rtf | 142 +++++++++++++++++++++++++ sw/qa/extras/rtfimport/rtfimport.cxx | 6 ++ writerfilter/source/rtftok/rtfdocumentimpl.cxx | 108 +++++++++++-------- writerfilter/source/rtftok/rtfdocumentimpl.hxx | 2 + 4 files changed, 211 insertions(+), 47 deletions(-) create mode 100644 sw/qa/extras/rtfimport/data/mathtype.rtf diff --git a/sw/qa/extras/rtfimport/data/mathtype.rtf b/sw/qa/extras/rtfimport/data/mathtype.rtf new file mode 100644 index 000000000000..411e8bd4d277 --- /dev/null +++ b/sw/qa/extras/rtfimport/data/mathtype.rtf @@ -0,0 +1,142 @@ +{\rtf1 +\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\hyphpar0\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af40\afs24\alang1081 \ltrch\fcs0 +\fs24\lang1033\langfe2052\kerning1\loch\af39\hich\af39\dbch\af1\cgrid\langnp1033\langfenp2052 +{\rtlch\fcs1 \af40 \ltrch\fcs0 \insrsid2305639 \hich\af39\dbch\af1\loch\f39 Before} +{\pard\plain \ltrpar +\ql \li0\ri0\nowidctlpar\wrapdefault\hyphpar0\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af40\afs24\alang1081 \ltrch\fcs0 \fs24\lang1033\langfe2052\kerning1\loch\af39\hich\af39\dbch\af1\cgrid\langnp1033\langfenp2052 +{\object\objemb +\objw617\objh566 +{\*\objclass Equation.3} +{\*\objdata 01050000020000000b0000004571756174696f6e2e33000000000000000000000c0000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdffffff04000000fefffffffefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff0100000002ce020000000000c0000000000000460000000000000000000000000000 +00000000000003000000000200000000000001004f006c00650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000200ffffffff02000000ffffffff00000000000000000000000000000000000000000000000000000000 +0000000000000000000000001400000000000000010043006f006d0070004f0062006a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000200ffffffff03000000ffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000100000066000000000000004500710075006100740069006f006e0020004e0061007400690076006500000000000000000000000000000000000000000000000000000000000000000000002000020004000000ffffffffffffffff000000000000000000000000000000000000000000000000 +000000000000000000000000030000004300000000000000feffffff02000000feffffff04000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100feff030a0000ffffffff02ce020000000000c0000000000000461700 +00004d6963726f736f6674204571756174696f6e20332e30000c0000004453204571756174696f6e000b0000004571756174696f6e2e3300f439b27100000000000000000000000000000000000000000000000000000000000000000000000000001c0000000200c6c1270000000000000090f61400b4eb140000000000 +03010103000a010a010283610002833d00030e00000a0102836200000a01028363000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030001000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000003004f0062006a0049006e0066006f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000200ffffffffffffffffffffffff000000000000 +000000000000000000000000000000000000000000000000000000000000050000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000} +{\result +{\rtlch\fcs1 \af40 \ltrch\fcs0 \insrsid2305639 +{\*\shppict +{\pict +{\*\picprop\shplid1025 +{\sp +{\sn shapeType} +{\sv 75} +} +{\sp +{\sn fFlipH} +{\sv 0} +} +{\sp +{\sn fFlipV} +{\sv 0} +} +{\sp +{\sn dxTextLeft} +{\sv 0} +} +{\sp +{\sn dyTextTop} +{\sv 0} +} +{\sp +{\sn dxTextRight} +{\sv 0} +} +{\sp +{\sn dyTextBottom} +{\sv 0} +} +{\sp +{\sn pictureActive} +{\sv 0} +} +{\sp +{\sn fillBackColor} +{\sv 0} +} +{\sp +{\sn fFilled} +{\sv 1} +} +{\sp +{\sn fLine} +{\sv 0} +} +{\sp +{\sn fLayoutInCell} +{\sv 1} +} +} +\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0 +\picw1088\pich998\picwgoal617\pichgoal566\emfblip\bliptag671316949 +{\*\blipuid 28037bd500000000c160369662020020} +010000006c0000000000000000000000280000002500000000000000000000003f040000e503000020454d4600000100180a00003d0000000400000000000000 +000000000000000029000000260000000a00000009000000000000000000000000000000802a0000fc260000460000002c00000020000000454d462b01400100 +1c000000100000000210c0db01000000660000006900000046000000580000004c000000454d462b224000000c000000000000001e4009000c00000000000000 +244000010c00000000000000304001000c00000000000000214000000c00000000000000044000000c00000000000000110000000c000000080000000b000000 +1000000060000000600000000900000010000000ec090000ec0900000c0000001000000000000000000000000a00000010000000000000000000000014000000 +0c0000000d000000120000000c0000000100000021000000080000001e0000001800000000000000000000003f040000e5030000210000000800000052000000 +4c010000010000005afeffff0000000000000000000000009001000001000000000000104c0069006200650072006100740069006f006e002000530065007200 +69006600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000160000000c00000018000000180000000c00000000000000250000000c0000000100000054000000540000006a000000610200003d010000 +220400000100000000000000000000006a00000061020000010000004c00000002000000000000000000000000000000000000005000000061000000d4000000 +220000000c000000ffffffff140000000c0000000d0000002100000008000000250000000c0000000a000080280000000c00000001000000520000004c010000 +010000005afeffff0000000000000000000000009001000000000000000000004f00700065006e00530079006d0062006f006c00000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000160000000c00000018000000180000000c00000000000000250000000c0000000100000054000000540000005801000061020000af02000071040000 +0100000000000000000000005801000061020000010000004c0000000200000000000000000000000000000000000000500000003d0000005801000022000000 +0c000000ffffffff140000000c0000000d0000002100000008000000250000000c0000000a000080280000000c00000001000000520000004c01000001000000 +5afeffff0000000000000000000000009001000001000000000000104c0069006200650072006100740069006f006e0020005300650072006900660000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +160000000c00000018000000180000000c00000000000000250000000c000000010000005400000054000000ca020000720100009d0300003303000001000000 +0000000000000000ca02000072010000010000004c00000002000000000000000000000000000000000000005000000062000000d4000000220000000c000000 +ffffffff140000000c0000000d0000002100000008000000270000001800000002000000000000000000000000000000250000000c0000000200000026000000 +1c00000003000000050000000000000000000000ffffff00250000000c000000030000002b00000018000000b0020000dc010000ba030000f001000022000000 +0c000000ffffffff140000000c0000000d0000002100000008000000250000000c0000000a000080280000000c00000001000000520000004c01000001000000 +5afeffff0000000000000000000000009001000001000000000000104c0069006200650072006100740069006f006e0020005300650072006900660000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +160000000c00000018000000180000000c00000000000000250000000c000000010000005400000054000000e5020000840300009d0300004505000001000000 +0000000000000000e502000084030000010000004c00000002000000000000000000000000000000000000005000000063000000b9000000220000000c000000 +ffffffff140000000c0000000d000000220000000c000000ffffffff140000000c0000000d000000460000001c00000010000000454d462b024000000c000000000000000e00000014000000000000001000000014000000} +} +} +} +} +} +\sectd \ltrsect\linex0\endnhere\sectdefaultcl\sftnbj +{\rtlch\fcs1 \af40 \ltrch\fcs0 +\insrsid2305639 \hich\af39\dbch\af1\loch\f39 after. +\par } +} diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx index 5262147cb6c1..c579403b7e78 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -2232,6 +2232,12 @@ DECLARE_RTFIMPORT_TEST(testFdo75614, "tdf75614.rtf") CPPUNIT_ASSERT_EQUAL(OUString("after."), getRun(getParagraph(1), 3)->getString()); } +DECLARE_RTFIMPORT_TEST(mathtype, "mathtype.rtf") +{ + OUString aFormula = getFormula(getRun(getParagraph(1), 1)); + CPPUNIT_ASSERT(!aFormula.isEmpty()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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 xInputStream(new utl::OInputStreamWrapper(m_pObjectData.get())); - auto pStreamValue = std::make_shared(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 xInputStream(new utl::OSeekableInputStreamWrapper(m_pObjectData.get())); + auto pStreamValue = std::make_shared(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 const& m_xContext; css::uno::Reference const& m_xInputStream; -- cgit v1.2.3