diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2017-07-10 18:47:49 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-07-13 11:21:04 +0200 |
commit | 427c763a1ad0ebc85383625f019b405c30828374 (patch) | |
tree | 766c2084bbe36fadc6f69a3458c3df4494a8a9a8 /embeddedobj/source | |
parent | a394d67f374e1b253f288a58113a3cfc8d301743 (diff) |
tdf#108545 tdf#108544: DOCX, XLSX embedded in DOC
When on Windows the MSO wasn't installed DOCX and XLSX
embedded documents weren't accessible. General OLE error
was shown after doubleclick on the object.
Linux solution is reused, OLE storage is extracted to
get the document inside.
Change-Id: If4d00fddad8e127fcf1a222836896d2907549d0c
Reviewed-on: https://gerrit.libreoffice.org/39814
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'embeddedobj/source')
-rw-r--r-- | embeddedobj/source/inc/oleembobj.hxx | 2 | ||||
-rw-r--r-- | embeddedobj/source/msole/oleembed.cxx | 65 |
2 files changed, 48 insertions, 19 deletions
diff --git a/embeddedobj/source/inc/oleembobj.hxx b/embeddedobj/source/inc/oleembobj.hxx index 2beb08e242fc..5df00c5e0a16 100644 --- a/embeddedobj/source/inc/oleembobj.hxx +++ b/embeddedobj/source/inc/oleembobj.hxx @@ -279,7 +279,7 @@ protected: void MoveListeners(); css::uno::Reference< css::embed::XStorage > CreateTemporarySubstorage( OUString& o_aStorageName ); OUString MoveToTemporarySubstream(); - bool TryToConvertToOOo(); + bool TryToConvertToOOo( const css::uno::Reference< css::io::XStream >& xStream ); public: // in case a new object must be created the class ID must be specified diff --git a/embeddedobj/source/msole/oleembed.cxx b/embeddedobj/source/msole/oleembed.cxx index f8c2c9903a73..c3acbb687e8b 100644 --- a/embeddedobj/source/msole/oleembed.cxx +++ b/embeddedobj/source/msole/oleembed.cxx @@ -248,7 +248,7 @@ OUString OleEmbeddedObject::MoveToTemporarySubstream() } -bool OleEmbeddedObject::TryToConvertToOOo() +bool OleEmbeddedObject::TryToConvertToOOo( const uno::Reference< io::XStream >& xStream ) { bool bResult = false; @@ -264,9 +264,9 @@ bool OleEmbeddedObject::TryToConvertToOOo() changeState( embed::EmbedStates::LOADED ); // the stream must be seekable - uno::Reference< io::XSeekable > xSeekable( m_xObjectStream, uno::UNO_QUERY_THROW ); + uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY_THROW ); xSeekable->seek( 0 ); - m_aFilterName = OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory, OUString(), m_xObjectStream->getInputStream() ); + m_aFilterName = OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory, OUString(), xStream->getInputStream() ); // use the solution only for OOXML format currently if ( !m_aFilterName.isEmpty() @@ -314,7 +314,7 @@ bool OleEmbeddedObject::TryToConvertToOOo() aArgs[3].Name = "URL"; aArgs[3].Value <<= OUString( "private:stream" ); aArgs[4].Name = "InputStream"; - aArgs[4].Value <<= m_xObjectStream->getInputStream(); + aArgs[4].Value <<= xStream->getInputStream(); xSeekable->seek( 0 ); xLoadable->load( aArgs ); @@ -657,7 +657,6 @@ sal_Int32 SAL_CALL OleEmbeddedObject::getCurrentState() namespace { -#ifndef _WIN32 bool lcl_CopyStream(const uno::Reference<io::XInputStream>& xIn, const uno::Reference<io::XOutputStream>& xOut, sal_Int32 nMaxCopy = SAL_MAX_INT32) { if (nMaxCopy == 0) @@ -679,18 +678,11 @@ namespace } while (nRead == nChunkSize && nTotalRead <= nMaxCopy); return nTotalRead != 0; } -#endif - //Dump the objects content to a tempfile, just the "CONTENTS" stream if - //there is one for non-compound documents, otherwise the whole content. - //On success a file is returned which must be removed by the caller - OUString lcl_ExtractObject(const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory, - const css::uno::Reference< css::io::XStream >& xObjectStream) + uno::Reference < io::XStream > lcl_GetExtractedStream( OUString& rUrl, + const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory, + const css::uno::Reference< css::io::XStream >& xObjectStream ) { - OUString sUrl; - - // the solution is only active for Unix systems -#ifndef _WIN32 uno::Reference <beans::XPropertySet> xNativeTempFile( io::TempFile::create(comphelper::getComponentContext(xFactory)), uno::UNO_QUERY_THROW); @@ -789,26 +781,48 @@ namespace xNativeTempFile->setPropertyValue("RemoveFile", uno::makeAny(false)); uno::Any aUrl = xNativeTempFile->getPropertyValue("Uri"); - aUrl >>= sUrl; + aUrl >>= rUrl; xNativeTempFile.clear(); uno::Reference < ucb::XSimpleFileAccess3 > xSimpleFileAccess( ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) ); - xSimpleFileAccess->setReadOnly(sUrl, true); + xSimpleFileAccess->setReadOnly(rUrl, true); } else { xNativeTempFile->setPropertyValue("RemoveFile", uno::makeAny(true)); } + + return xStream; + } + + //Dump the objects content to a tempfile, just the "CONTENTS" stream if + //there is one for non-compound documents, otherwise the whole content. + //On success a file is returned which must be removed by the caller + OUString lcl_ExtractObject(const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory, + const css::uno::Reference< css::io::XStream >& xObjectStream) + { + OUString sUrl; + + // the solution is only active for Unix systems +#ifndef _WIN32 + lcl_GetExtractedStream(sUrl, xFactory, xObjectStream); #else (void) xFactory; (void) xObjectStream; #endif return sUrl; } + + uno::Reference < io::XStream > lcl_ExtractObjectStream( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory, + const css::uno::Reference< css::io::XStream >& xObjectStream ) + { + OUString sUrl; + return lcl_GetExtractedStream( sUrl, xFactory, xObjectStream ); + } } @@ -818,6 +832,9 @@ void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID ) uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; if ( xWrappedObject.is() ) { + // open content in the window not in-place + nVerbID = embed::EmbedVerbs::MS_OLEVERB_OPEN; + // the object was converted to OOo embedded object, the current implementation is now only a wrapper xWrappedObject->doVerb( nVerbID ); return; @@ -890,7 +907,7 @@ void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID ) if ( !m_bTriedConversion ) { m_bTriedConversion = true; - if ( TryToConvertToOOo() ) + if ( TryToConvertToOOo( m_xObjectStream ) ) { changeState( embed::EmbedStates::UI_ACTIVE ); return; @@ -917,6 +934,18 @@ void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID ) } } + // it may be the OLE Storage, try to extract stream + if ( !m_xOwnView.is() && m_xObjectStream.is() && m_aFilterName == "Text" ) + { + uno::Reference< io::XStream > xStream = lcl_ExtractObjectStream( m_xFactory, m_xObjectStream ); + + if ( TryToConvertToOOo( xStream ) ) + { + changeState( embed::EmbedStates::ACTIVE ); + return; + } + } + if (!m_xOwnView.is() || !m_xOwnView->Open()) { //Make a RO copy and see if the OS can find something to at |