diff options
Diffstat (limited to 'embeddedobj/source/commonembedding/persistence.cxx')
-rw-r--r-- | embeddedobj/source/commonembedding/persistence.cxx | 117 |
1 files changed, 87 insertions, 30 deletions
diff --git a/embeddedobj/source/commonembedding/persistence.cxx b/embeddedobj/source/commonembedding/persistence.cxx index f162dfef5f31..e568b1232a71 100644 --- a/embeddedobj/source/commonembedding/persistence.cxx +++ b/embeddedobj/source/commonembedding/persistence.cxx @@ -47,14 +47,18 @@ #include <com/sun/star/beans/IllegalTypeException.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> +#include <com/sun/star/io/XTruncate.hpp> + #include <comphelper/fileformat.h> #include <comphelper/storagehelper.hxx> #include <comphelper/mimeconfighelper.hxx> #include <comphelper/namedvaluecollection.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/securityoptions.hxx> #include <tools/diagnose_ex.h> #include <sal/log.hxx> -#include <unotools/configmgr.hxx> #include "persistence.hxx" using namespace ::com::sun::star; @@ -75,7 +79,7 @@ uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< || aMedDescr[nInd].Name == "StartPresentation" || aMedDescr[nInd].Name == "RepairPackage" || aMedDescr[nInd].Name == "StatusIndicator" || aMedDescr[nInd].Name == "ViewData" || aMedDescr[nInd].Name == "ViewId" || aMedDescr[nInd].Name == "MacroExecutionMode" - || aMedDescr[nInd].Name == "UpdateDocMode" + || aMedDescr[nInd].Name == "UpdateDocMode" || aMedDescr[nInd].Name == "Referer" || (aMedDescr[nInd].Name == "DocumentBaseURL" && bCanUseDocumentBaseURL) ) { aResult.realloc( ++nResLen ); @@ -254,7 +258,7 @@ void OCommonEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::X m_aEntryName = aNewName; // the linked document should not be switched - if ( !m_bIsLink ) + if ( !m_bIsLinkURL ) { uno::Reference< document::XStorageBasedDocument > xDoc( m_xDocHolder->GetComponent(), uno::UNO_QUERY ); if ( xDoc.is() ) @@ -359,20 +363,20 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::InitNewDocument_Impl() return xDocument; } - uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() { - uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(), - m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); - - uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY_THROW ); - sal_Int32 nLen = 2; uno::Sequence< beans::PropertyValue > aArgs( nLen ); + aArgs[0].Name = "URL"; - aArgs[0].Value <<= m_aLinkURL; + if(m_aLinkTempFile.is()) + aArgs[0].Value <<= m_aLinkTempFile->getUri(); + else + aArgs[0].Value <<= m_aLinkURL; + aArgs[1].Name = "FilterName"; aArgs[1].Value <<= m_aLinkFilterName; + if ( m_bLinkHasPassword ) { aArgs.realloc( ++nLen ); @@ -383,10 +387,22 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() aArgs.realloc( m_aDocMediaDescriptor.getLength() + nLen ); for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ ) { + // return early if this document is not trusted to open links + if (m_aDocMediaDescriptor[nInd].Name == "Referer") + { + OUString referer; + m_aDocMediaDescriptor[nInd].Value >>= referer; + if (SvtSecurityOptions().isUntrustedReferer(referer)) + return nullptr; + } aArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name; aArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value; } + uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(), + m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); + uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY_THROW ); + try { // the document is not really an embedded one, it is a link @@ -428,7 +444,6 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() } - OUString OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion ) const { OUString aFilterName = GetPresetFilterName(); @@ -847,7 +862,7 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_ { uno::Reference< util::XCloseable > xResult; - SAL_WARN_IF( !m_bIsLink, "embeddedobj.common", "The object is not a linked one!" ); + SAL_WARN_IF( !m_bIsLinkURL, "embeddedobj.common", "The object is not a linked one!" ); uno::Sequence< beans::PropertyValue > aTempMediaDescr; @@ -899,7 +914,12 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_ { aTempMediaDescr.realloc( 2 ); aTempMediaDescr[0].Name = "URL"; - aTempMediaDescr[0].Value <<= m_aLinkURL; + + // tdf#141529 use URL of the linked TempFile if it exists + aTempMediaDescr[0].Value <<= m_aLinkTempFile.is() + ? m_aLinkTempFile->getUri() + : m_aLinkURL; + aTempMediaDescr[1].Name = "FilterName"; aTempMediaDescr[1].Value <<= m_aLinkFilterName; } @@ -972,8 +992,8 @@ void SAL_CALL OCommonEmbeddedObject::setPersistentEntry( // for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) - // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" ); - if ( m_bIsLink ) + // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); + if ( m_bIsLinkURL ) { m_aEntryName = sEntName; return; @@ -1151,8 +1171,8 @@ void SAL_CALL OCommonEmbeddedObject::storeToEntry( const uno::Reference< embed:: // for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) - // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" ); - if ( m_bIsLink ) + // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); + if ( m_bIsLinkURL ) return; OSL_ENSURE( m_xParentStorage.is() && m_xObjectStorage.is(), "The object has no valid persistence!" ); @@ -1279,10 +1299,33 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed:: // for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) - // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" ); - if ( m_bIsLink ) + // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); + if ( m_bIsLinkURL ) { m_aNewEntryName = sEntName; + + if(m_aLinkTempFile.is() && m_bLinkTempFileChanged) + { + // tdf#141529 if we have a changed copy of the original OLE data we now + // need to write it back 'over' the original OLE data + uno::Reference < ucb::XSimpleFileAccess2 > xFileAccess(ucb::SimpleFileAccess::create( m_xContext )); + uno::Reference < io::XInputStream > xTempIn = m_aLinkTempFile->getInputStream(); + + // This is *needed* since OTempFileService calls OTempFileService::readBytes which + // ensures the SvStream mpStream gets/is opened, *but* also sets the mnCachedPos from + // OTempFileService which still points to the end-of-file (from write-cc'ing). + uno::Reference < io::XSeekable > xSeek( xTempIn, uno::UNO_QUERY_THROW ); + xSeek->seek(0); + + xFileAccess->writeFile(m_aLinkURL, xTempIn); + + // Do *not* close input, that would remove the temporary file too early + // xTempIn->closeInput(); + + // reset flag m_bLinkTempFileChanged + m_bLinkTempFileChanged = false; + } + return; } @@ -1411,8 +1454,8 @@ void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew ) // for now support of this interface is required to allow breaking of links and converting them to normal embedded // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) - // OSL_ENSURE( !m_bIsLink, "This method implementation must not be used for links!" ); - if ( m_bIsLink ) + // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); + if ( m_bIsLinkURL ) { if ( bUseNew ) m_aEntryName = m_aNewEntryName; @@ -1546,7 +1589,7 @@ void SAL_CALL OCommonEmbeddedObject::storeOwn() if ( !m_xDocHolder->GetComponent().is() ) throw uno::RuntimeException(); - if ( m_bIsLink ) + if ( m_bIsLinkURL ) { // TODO: just store the document to its location uno::Reference< frame::XStorable > xStorable( m_xDocHolder->GetComponent(), uno::UNO_QUERY_THROW ); @@ -1654,7 +1697,7 @@ void SAL_CALL OCommonEmbeddedObject::reload( "The object waits for saveCompleted() call!", static_cast< ::cppu::OWeakObject* >(this) ); - if ( m_bIsLink ) + if ( m_bIsLinkURL ) { // reload of the link OUString aOldLinkFilter = m_aLinkFilterName; @@ -1723,7 +1766,7 @@ void SAL_CALL OCommonEmbeddedObject::reload( if ( lArguments[nInd].Name == "ReadOnly" ) lArguments[nInd].Value >>= m_bReadOnly; - if ( bOldReadOnlyValue != m_bReadOnly && !m_bIsLink ) + if ( bOldReadOnlyValue != m_bReadOnly && !m_bIsLinkURL ) { // close own storage try { @@ -1755,7 +1798,7 @@ void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XSt if ( m_bDisposed ) throw lang::DisposedException(); // TODO - if (!m_bIsLink || m_nObjectState == -1) + if (!m_bIsLinkURL || m_nObjectState == -1) { // it must be a linked initialized object throw embed::WrongStateException( @@ -1793,10 +1836,21 @@ void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XSt // TODO/LATER: handle the case when temp doc can not be created // the document is a new embedded object so it must be marked as modified uno::Reference< util::XCloseable > xDocument = CreateTempDocFromLink_Impl(); - uno::Reference< util::XModifiable > xModif( m_xDocHolder->GetComponent(), uno::UNO_QUERY_THROW ); try { - xModif->setModified( true ); + if(m_xDocHolder.is() && m_xDocHolder->GetComponent().is()) + { + // tdf#141528 m_xDocHolder->GetComponent() may be not set, so add it + // to the try path to not get thrown out of the local context to the next + // highter try...catch on the stack. To make breakLink work it is + // *necessary* to execute the code below that resets the linked state, + // esp. the *.clear stuff and resetting m_bIsLink. + uno::Reference< util::XModifiable > xModif( m_xDocHolder->GetComponent(), uno::UNO_QUERY_THROW ); + + // all other locations in this file check for xModif.is(), so do it here, too + if ( xModif.is() ) + xModif->setModified( true ); + } } catch( const uno::Exception& ) {} @@ -1813,7 +1867,10 @@ void SAL_CALL OCommonEmbeddedObject::breakLink( const uno::Reference< embed::XSt else if ( m_nObjectState == embed::EmbedStates::ACTIVE ) m_xDocHolder->Show(); - m_bIsLink = false; + // tdf#141529 reset all stuff involved in linked state, including + // the OLE content copied to the temp file + m_bIsLinkURL = false; + m_aLinkTempFile.clear(); m_aLinkFilterName.clear(); m_aLinkURL.clear(); } @@ -1825,7 +1882,7 @@ sal_Bool SAL_CALL OCommonEmbeddedObject::isLink() if ( m_bDisposed ) throw lang::DisposedException(); // TODO - return m_bIsLink; + return m_bIsLinkURL; } @@ -1835,7 +1892,7 @@ OUString SAL_CALL OCommonEmbeddedObject::getLinkURL() if ( m_bDisposed ) throw lang::DisposedException(); // TODO - if ( !m_bIsLink ) + if ( !m_bIsLinkURL ) throw embed::WrongStateException( "The object is not a link object!", static_cast< ::cppu::OWeakObject* >(this) ); |