diff options
Diffstat (limited to 'embeddedobj/source/commonembedding/persistence.cxx')
-rw-r--r-- | embeddedobj/source/commonembedding/persistence.cxx | 273 |
1 files changed, 168 insertions, 105 deletions
diff --git a/embeddedobj/source/commonembedding/persistence.cxx b/embeddedobj/source/commonembedding/persistence.cxx index 6dda3c67830b..80fc047b1016 100644 --- a/embeddedobj/source/commonembedding/persistence.cxx +++ b/embeddedobj/source/commonembedding/persistence.cxx @@ -47,14 +47,19 @@ #include <com/sun/star/beans/IllegalTypeException.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> + #include <comphelper/fileformat.h> #include <comphelper/storagehelper.hxx> #include <comphelper/mimeconfighelper.hxx> #include <comphelper/namedvaluecollection.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/configuration.hxx> +#include <unotools/mediadescriptor.hxx> +#include <unotools/securityoptions.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <sal/log.hxx> -#include <unotools/configmgr.hxx> #include "persistence.hxx" using namespace ::com::sun::star; @@ -75,11 +80,11 @@ uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< || prop.Name == "StartPresentation" || prop.Name == "RepairPackage" || prop.Name == "StatusIndicator" || prop.Name == "ViewData" || prop.Name == "ViewId" || prop.Name == "MacroExecutionMode" - || prop.Name == "UpdateDocMode" + || prop.Name == "UpdateDocMode" || prop.Name == "Referer" || (prop.Name == "DocumentBaseURL" && bCanUseDocumentBaseURL) ) { aResult.realloc( ++nResLen ); - aResult[nResLen-1] = prop; + aResult.getArray()[nResLen-1] = prop; } } @@ -91,25 +96,23 @@ static uno::Sequence< beans::PropertyValue > addAsTemplate( const uno::Sequence< { bool bAsTemplateSet = false; sal_Int32 nLength = aOrig.getLength(); - uno::Sequence< beans::PropertyValue > aResult( nLength ); + uno::Sequence< beans::PropertyValue > aResult( aOrig ); for ( sal_Int32 nInd = 0; nInd < nLength; nInd++ ) { - aResult[nInd].Name = aOrig[nInd].Name; if ( aResult[nInd].Name == "AsTemplate" ) { - aResult[nInd].Value <<= true; + aResult.getArray()[nInd].Value <<= true; bAsTemplateSet = true; } - else - aResult[nInd].Value = aOrig[nInd].Value; } if ( !bAsTemplateSet ) { aResult.realloc( nLength + 1 ); - aResult[nLength].Name = "AsTemplate"; - aResult[nLength].Value <<= true; + auto pResult = aResult.getArray(); + pResult[nLength].Name = "AsTemplate"; + pResult[nLength].Value <<= true; } return aResult; @@ -128,9 +131,8 @@ static uno::Reference< io::XInputStream > createTempInpStreamFromStor( uno::Reference < lang::XSingleServiceFactory > xStorageFactory( embed::StorageFactory::create(xContext) ); - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xTempStream; - aArgs[1] <<= embed::ElementModes::READWRITE; + uno::Sequence< uno::Any > aArgs{ uno::Any(xTempStream), + uno::Any(embed::ElementModes::READWRITE) }; uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); @@ -176,7 +178,7 @@ static void TransferMediaType( const uno::Reference< embed::XStorage >& i_rSourc { const uno::Reference< beans::XPropertySet > xSourceProps( i_rSource, uno::UNO_QUERY_THROW ); const uno::Reference< beans::XPropertySet > xTargetProps( i_rTarget, uno::UNO_QUERY_THROW ); - const OUString sMediaTypePropName( "MediaType" ); + static constexpr OUString sMediaTypePropName( u"MediaType"_ustr ); xTargetProps->setPropertyValue( sMediaTypePropName, xSourceProps->getPropertyValue( sMediaTypePropName ) ); } catch( const uno::Exception& ) @@ -189,10 +191,13 @@ static void TransferMediaType( const uno::Reference< embed::XStorage >& i_rSourc static uno::Reference< util::XCloseable > CreateDocument( const uno::Reference< uno::XComponentContext >& _rxContext, const OUString& _rDocumentServiceName, bool _bEmbeddedScriptSupport, const bool i_bDocumentRecoverySupport ) { + static constexpr OUStringLiteral sEmbeddedObject = u"EmbeddedObject"; + static constexpr OUStringLiteral sEmbeddedScriptSupport = u"EmbeddedScriptSupport"; + static constexpr OUStringLiteral sDocumentRecoverySupport = u"DocumentRecoverySupport"; ::comphelper::NamedValueCollection aArguments; - aArguments.put( "EmbeddedObject", true ); - aArguments.put( "EmbeddedScriptSupport", _bEmbeddedScriptSupport ); - aArguments.put( "DocumentRecoverySupport", i_bDocumentRecoverySupport ); + aArguments.put( sEmbeddedObject, true ); + aArguments.put( sEmbeddedScriptSupport, _bEmbeddedScriptSupport ); + aArguments.put( sDocumentRecoverySupport, i_bDocumentRecoverySupport ); uno::Reference< uno::XInterface > xDocument; try @@ -220,9 +225,7 @@ static void SetDocToEmbedded( const uno::Reference< frame::XModel >& rDocument, if (!rDocument.is()) return; - uno::Sequence< beans::PropertyValue > aSeq( 1 ); - aSeq[0].Name = "SetEmbedded"; - aSeq[0].Value <<= true; + uno::Sequence< beans::PropertyValue > aSeq{ comphelper::makePropertyValue("SetEmbedded", true) }; rDocument->attachResource( OUString(), aSeq ); if ( !aModuleName.isEmpty() ) @@ -254,7 +257,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,36 +362,84 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::InitNewDocument_Impl() return xDocument; } +bool OCommonEmbeddedObject::getAllowLinkUpdate() const +{ + // assume we can update if we can't determine a parent + bool bAllowLinkUpdate(true); + + try + { + uno::Reference<container::XChild> xParent(m_xParent, uno::UNO_QUERY); + while (xParent) + { + uno::Reference<container::XChild> xGrandParent(xParent->getParent(), uno::UNO_QUERY); + if (!xGrandParent) + break; + xParent = xGrandParent; + } + + uno::Reference<beans::XPropertySet> xPropSet(xParent, uno::UNO_QUERY); + if (xPropSet.is()) + { + uno::Any aAny = xPropSet->getPropertyValue("AllowLinkUpdate"); + aAny >>= bAllowLinkUpdate; + } + } + catch (const uno::Exception&) + { + } + + SAL_WARN_IF(!bAllowLinkUpdate, "embeddedobj.common", "getAllowLinkUpdate is false"); + + return bAllowLinkUpdate; +} uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() { - uno::Reference< util::XCloseable > xDocument( CreateDocument( m_xContext, GetDocumentServiceName(), - m_bEmbeddedScriptSupport, m_bDocumentRecoverySupport ) ); + if (!getAllowLinkUpdate()) + return nullptr; - uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY_THROW ); + sal_Int32 nLen = m_bLinkHasPassword ? 3 : 2; + uno::Sequence< beans::PropertyValue > aArgs( m_aDocMediaDescriptor.getLength() + nLen ); + auto pArgs = aArgs.getArray(); + + pArgs[0].Name = "URL"; + if(m_aLinkTempFile.is()) + pArgs[0].Value <<= m_aLinkTempFile->getUri(); + else + pArgs[0].Value <<= m_aLinkURL; + + pArgs[1].Name = "FilterName"; + pArgs[1].Value <<= m_aLinkFilterName; - sal_Int32 nLen = 2; - uno::Sequence< beans::PropertyValue > aArgs( nLen ); - aArgs[0].Name = "URL"; - aArgs[0].Value <<= m_aLinkURL; - aArgs[1].Name = "FilterName"; - aArgs[1].Value <<= m_aLinkFilterName; if ( m_bLinkHasPassword ) { - aArgs.realloc( ++nLen ); - aArgs[nLen-1].Name = "Password"; - aArgs[nLen-1].Value <<= m_aLinkPassword; + pArgs[2].Name = "Password"; + pArgs[2].Value <<= m_aLinkPassword; } - aArgs.realloc( m_aDocMediaDescriptor.getLength() + nLen ); for ( sal_Int32 nInd = 0; nInd < m_aDocMediaDescriptor.getLength(); nInd++ ) { - aArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name; - aArgs[nInd+nLen].Value = m_aDocMediaDescriptor[nInd].Value; + // return early if this document is not trusted to open links + if (m_aDocMediaDescriptor[nInd].Name == utl::MediaDescriptor::PROP_REFERRER) + { + OUString referer; + m_aDocMediaDescriptor[nInd].Value >>= referer; + if (SvtSecurityOptions::isUntrustedReferer(referer)) + return nullptr; + } + pArgs[nInd+nLen].Name = m_aDocMediaDescriptor[nInd].Name; + pArgs[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 { + handleLinkedOLE(CopyBackToOLELink::CopyLinkToTemp); + // the document is not really an embedded one, it is a link EmbedAndReparentDoc_Impl( xDocument ); @@ -428,14 +479,13 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() } - OUString OCommonEmbeddedObject::GetFilterName( sal_Int32 nVersion ) const { OUString aFilterName = GetPresetFilterName(); if ( aFilterName.isEmpty() ) { OUString sDocumentServiceName = GetDocumentServiceName(); - if (utl::ConfigManager::IsFuzzing() && nVersion == SOFFICE_FILEFORMAT_CURRENT && + if (comphelper::IsFuzzing() && nVersion == SOFFICE_FILEFORMAT_CURRENT && sDocumentServiceName == "com.sun.star.chart2.ChartDocument") { return "chart8"; @@ -530,6 +580,11 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadDocumentFromStorag // set the document mode to embedded as the first step!!! EmbedAndReparentDoc_Impl( xDocument ); + if (m_bReadOnly) + { + aLoadArgs.put("ReadOnly", true); + } + if ( xDoc.is() ) { xDoc->loadFromStorage( xSourceStorage, aLoadArgs.getPropertyValues() ); @@ -578,23 +633,20 @@ uno::Reference< io::XInputStream > OCommonEmbeddedObject::StoreDocumentToTempStr } if( !xStorable.is() ) - throw uno::RuntimeException(); // TODO: + throw uno::RuntimeException("No storage is provided for storing!"); // TODO: OUString aFilterName = GetFilterName( nStorageFormat ); SAL_WARN_IF( aFilterName.isEmpty(), "embeddedobj.common", "Wrong document service name!" ); if ( aFilterName.isEmpty() ) - throw io::IOException(); // TODO: - - uno::Sequence< beans::PropertyValue > aArgs( 4 ); - aArgs[0].Name = "FilterName"; - aArgs[0].Value <<= aFilterName; - aArgs[1].Name = "OutputStream"; - aArgs[1].Value <<= xTempOut; - aArgs[2].Name = "DocumentBaseURL"; - aArgs[2].Value <<= aBaseURL; - aArgs[3].Name = "HierarchicalDocumentName"; - aArgs[3].Value <<= aHierarchName; + throw io::IOException("No filter name provided / Wrong document service name"); // TODO: + + uno::Sequence< beans::PropertyValue > aArgs{ + comphelper::makePropertyValue("FilterName", aFilterName), + comphelper::makePropertyValue("OutputStream", xTempOut), + comphelper::makePropertyValue("DocumentBaseURL", aBaseURL), + comphelper::makePropertyValue("HierarchicalDocumentName", aHierarchName) + }; xStorable->storeToURL( "private:stream", aArgs ); try @@ -715,7 +767,8 @@ void OCommonEmbeddedObject::SwitchDocToStorage_Impl( const uno::Reference< docum namespace { -OUString getStringPropertyValue( const uno::Sequence<beans::PropertyValue>& rProps, std::u16string_view rName ) +beans::PropertyValue getStringPropertyValue(const uno::Sequence<beans::PropertyValue>& rProps, + const OUString& rName) { OUString aStr; @@ -728,7 +781,7 @@ OUString getStringPropertyValue( const uno::Sequence<beans::PropertyValue>& rPro } } - return aStr; + return comphelper::makePropertyValue(rName, aStr); } } @@ -767,17 +820,13 @@ void OCommonEmbeddedObject::StoreDocToStorage_Impl( if ( aFilterName.isEmpty() ) throw io::IOException(); // TODO: - uno::Sequence<beans::PropertyValue> aArgs(5); - aArgs[0].Name = "FilterName"; - aArgs[0].Value <<= aFilterName; - aArgs[1].Name = "HierarchicalDocumentName"; - aArgs[1].Value <<= aHierarchName; - aArgs[2].Name = "DocumentBaseURL"; - aArgs[2].Value <<= aBaseURL; - aArgs[3].Name = "SourceShellID"; - aArgs[3].Value <<= getStringPropertyValue(rObjArgs, u"SourceShellID"); - aArgs[4].Name = "DestinationShellID"; - aArgs[4].Value <<= getStringPropertyValue(rObjArgs, u"DestinationShellID"); + uno::Sequence<beans::PropertyValue> aArgs{ + comphelper::makePropertyValue(u"FilterName"_ustr, aFilterName), + comphelper::makePropertyValue(u"HierarchicalDocumentName"_ustr, aHierarchName), + comphelper::makePropertyValue(u"DocumentBaseURL"_ustr, aBaseURL), + getStringPropertyValue(rObjArgs, u"SourceShellID"_ustr), + getStringPropertyValue(rObjArgs, u"DestinationShellID"_ustr), + }; xDoc->storeToStorage( xStorage, aArgs ); if ( bAttachToTheStorage ) @@ -793,8 +842,7 @@ void OCommonEmbeddedObject::StoreDocToStorage_Impl( // open storage based on document temporary file for reading uno::Reference < lang::XSingleServiceFactory > xStorageFactory = embed::StorageFactory::create(m_xContext); - uno::Sequence< uno::Any > aArgs(1); - aArgs[0] <<= xTempIn; + uno::Sequence< uno::Any > aArgs{ uno::Any(xTempIn) }; uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); @@ -843,7 +891,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; @@ -882,22 +930,19 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::CreateTempDocFromLink_ SAL_WARN_IF( aTempFileURL.isEmpty(), "embeddedobj.common", "Couldn't retrieve temporary file URL!" ); - aTempMediaDescr[0].Name = "URL"; - aTempMediaDescr[0].Value <<= aTempFileURL; - aTempMediaDescr[1].Name = "InputStream"; - aTempMediaDescr[1].Value <<= xTempStream; - aTempMediaDescr[2].Name = "FilterName"; - aTempMediaDescr[2].Value <<= GetFilterName( nStorageFormat ); - aTempMediaDescr[3].Name = "AsTemplate"; - aTempMediaDescr[3].Value <<= true; + aTempMediaDescr + = { comphelper::makePropertyValue("URL", aTempFileURL), + comphelper::makePropertyValue("InputStream", xTempStream), + comphelper::makePropertyValue("FilterName", GetFilterName( nStorageFormat )), + comphelper::makePropertyValue("AsTemplate", true) }; } else { - aTempMediaDescr.realloc( 2 ); - aTempMediaDescr[0].Name = "URL"; - aTempMediaDescr[0].Value <<= m_aLinkURL; - aTempMediaDescr[1].Name = "FilterName"; - aTempMediaDescr[1].Value <<= m_aLinkFilterName; + aTempMediaDescr = { comphelper::makePropertyValue( + "URL", + // tdf#141529 use URL of the linked TempFile if it exists + m_aLinkTempFile.is() ? m_aLinkTempFile->getUri() : m_aLinkURL), + comphelper::makePropertyValue("FilterName", m_aLinkFilterName) }; } xResult = CreateDocFromMediaDescr_Impl( aTempMediaDescr ); @@ -968,8 +1013,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; @@ -1147,8 +1192,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!" ); @@ -1255,12 +1300,14 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed:: const uno::Sequence< beans::PropertyValue >& lArguments, const uno::Sequence< beans::PropertyValue >& lObjArgs ) { - // TODO: use lObjArgs - ::osl::ResettableMutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO + bool AutoSaveEvent = false; + utl::MediaDescriptor lArgs(lObjArgs); + lArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent; + if ( m_nObjectState == -1 ) { // the object is still not loaded @@ -1275,10 +1322,14 @@ 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 ( !AutoSaveEvent ) + handleLinkedOLE(CopyBackToOLELink::CopyTempToLink); + return; } @@ -1407,8 +1458,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; @@ -1542,7 +1593,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 ); @@ -1582,9 +1633,8 @@ void SAL_CALL OCommonEmbeddedObject::storeOwn() aGuard.clear(); uno::Sequence<beans::PropertyValue> aEmpty; - uno::Sequence<beans::PropertyValue> aMediaArgs(1); - aMediaArgs[0].Name = "DocumentBaseURL"; - aMediaArgs[0].Value <<= GetBaseURL_Impl(); + uno::Sequence<beans::PropertyValue> aMediaArgs{ comphelper::makePropertyValue( + "DocumentBaseURL", GetBaseURL_Impl()) }; StoreDocToStorage_Impl( m_xObjectStorage, aMediaArgs, aEmpty, nStorageFormat, m_aEntryName, true ); aGuard.reset(); } @@ -1650,7 +1700,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; @@ -1678,9 +1728,8 @@ void SAL_CALL OCommonEmbeddedObject::reload( m_aLinkFilterName = aNewLinkFilter; else { - uno::Sequence< beans::PropertyValue > aArgs( 1 ); - aArgs[0].Name = "URL"; - aArgs[0].Value <<= m_aLinkURL; + uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue( + "URL", m_aLinkURL) }; m_aLinkFilterName = aHelper.UpdateMediaDescriptorWithFilterName( aArgs, false ); } } @@ -1719,7 +1768,7 @@ void SAL_CALL OCommonEmbeddedObject::reload( if ( prop.Name == "ReadOnly" ) prop.Value >>= m_bReadOnly; - if ( bOldReadOnlyValue == m_bReadOnly || m_bIsLink ) + if ( bOldReadOnlyValue == m_bReadOnly || m_bIsLinkURL ) return; // close own storage @@ -1751,7 +1800,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( @@ -1789,10 +1838,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 + // higher 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& ) {} @@ -1809,7 +1869,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(); } @@ -1821,7 +1884,7 @@ sal_Bool SAL_CALL OCommonEmbeddedObject::isLink() if ( m_bDisposed ) throw lang::DisposedException(); // TODO - return m_bIsLink; + return m_bIsLinkURL; } @@ -1831,7 +1894,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) ); |