diff options
Diffstat (limited to 'sfx2/source/doc/objmisc.cxx')
-rw-r--r-- | sfx2/source/doc/objmisc.cxx | 1920 |
1 files changed, 1920 insertions, 0 deletions
diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx new file mode 100644 index 000000000..873ab8b9b --- /dev/null +++ b/sfx2/source/doc/objmisc.cxx @@ -0,0 +1,1920 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <tools/inetmsg.hxx> +#include <tools/diagnose_ex.h> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <svtools/svparser.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <sal/log.hxx> +#include <o3tl/string_view.hxx> + +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/document/XScriptInvocationContext.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp> +#include <com/sun/star/script/provider/XScript.hpp> +#include <com/sun/star/script/provider/XScriptProvider.hpp> +#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp> +#include <com/sun/star/uri/UriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp> +#include <com/sun/star/util/XModifiable.hpp> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/task/ErrorCodeRequest.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/string.hxx> + +#include <com/sun/star/security/DocumentDigitalSignatures.hpp> +#include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp> +#include <com/sun/star/task/InteractionClassification.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/frame/XModel.hpp> + +#include <basic/basmgr.hxx> +#include <basic/sberrors.hxx> +#include <vcl/weld.hxx> +#include <basic/sbx.hxx> +#include <svtools/sfxecode.hxx> + +#include <unotools/ucbhelper.hxx> +#include <tools/urlobj.hxx> +#include <svl/sharecontrolfile.hxx> +#include <rtl/uri.hxx> +#include <vcl/svapp.hxx> +#include <framework/interaction.hxx> +#include <framework/documentundoguard.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/documentconstants.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <officecfg/Office/Common.hxx> + +#include <sfx2/signaturestate.hxx> +#include <sfx2/app.hxx> +#include <appdata.hxx> +#include <sfx2/request.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/sfxresid.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/objsh.hxx> +#include <objshimp.hxx> +#include <sfx2/event.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxuno.hxx> +#include <sfx2/module.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/strings.hrc> +#include <workwin.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/infobar.hxx> +#include <sfx2/sfxbasemodel.hxx> +#include <openflag.hxx> +#include "objstor.hxx" +#include <appopen.hxx> + +#include <memory> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::script::provider; +using namespace ::com::sun::star::container; + +// class SfxHeaderAttributes_Impl ---------------------------------------- + +namespace { + +class SfxHeaderAttributes_Impl : public SvKeyValueIterator +{ +private: + SfxObjectShell* pDoc; + SvKeyValueIteratorRef xIter; + bool bAlert; + +public: + explicit SfxHeaderAttributes_Impl( SfxObjectShell* pSh ) : + pDoc( pSh ), + xIter( pSh->GetMedium()->GetHeaderAttributes_Impl() ), + bAlert( false ) {} + + virtual bool GetFirst( SvKeyValue& rKV ) override { return xIter->GetFirst( rKV ); } + virtual bool GetNext( SvKeyValue& rKV ) override { return xIter->GetNext( rKV ); } + virtual void Append( const SvKeyValue& rKV ) override; + + void ClearForSourceView() { xIter = new SvKeyValueIterator; bAlert = false; } + void SetAttributes(); + void SetAttribute( const SvKeyValue& rKV ); +}; + +} + +sal_uInt16 const aTitleMap_Impl[3][2] = +{ + // local remote + /* SFX_TITLE_CAPTION */ { SFX_TITLE_FILENAME, SFX_TITLE_TITLE }, + /* SFX_TITLE_PICKLIST */ { 32, SFX_TITLE_FULLNAME }, + /* SFX_TITLE_HISTORY */ { 32, SFX_TITLE_FULLNAME } +}; + + +bool SfxObjectShell::IsAbortingImport() const +{ + return pImpl->bIsAbortingImport; +} + + +uno::Reference<document::XDocumentProperties> +SfxObjectShell::getDocProperties() const +{ + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + GetModel(), uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentProperties> xDocProps( + xDPS->getDocumentProperties()); + DBG_ASSERT(xDocProps.is(), + "SfxObjectShell: model has no DocumentProperties"); + return xDocProps; +} + + +void SfxObjectShell::DoFlushDocInfo() +{ +} + + +// Note: the only thing that calls this is the modification event handler +// that is installed at the XDocumentProperties +void SfxObjectShell::FlushDocInfo() +{ + if ( IsLoading() ) + return; + + SetModified(); + uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties()); + DoFlushDocInfo(); // call template method + const OUString url(xDocProps->getAutoloadURL()); + sal_Int32 delay(xDocProps->getAutoloadSecs()); + SetAutoLoad( INetURLObject(url), delay * 1000, + (delay > 0) || !url.isEmpty() ); +} + +void SfxObjectShell::AppendInfoBarWhenReady(const OUString& sId, const OUString& sPrimaryMessage, + const OUString& sSecondaryMessage, + InfobarType aInfobarType, bool bShowCloseButton) +{ + InfobarData aInfobarData; + aInfobarData.msId = sId; + aInfobarData.msPrimaryMessage = sPrimaryMessage; + aInfobarData.msSecondaryMessage = sSecondaryMessage; + aInfobarData.maInfobarType = aInfobarType; + aInfobarData.mbShowCloseButton = bShowCloseButton; + Get_Impl()->m_aPendingInfobars.emplace_back(aInfobarData); +} + +std::vector<InfobarData>& SfxObjectShell::getPendingInfobars() +{ + return Get_Impl()->m_aPendingInfobars; +} + +void SfxObjectShell::SetError(ErrCode lErr) +{ + if (pImpl->lErr==ERRCODE_NONE) + { + pImpl->lErr=lErr; + } +} + +ErrCode SfxObjectShell::GetError() const +{ + return GetErrorCode().IgnoreWarning(); +} + +ErrCode SfxObjectShell::GetErrorCode() const +{ + ErrCode lError=pImpl->lErr; + if(!lError && GetMedium()) + lError=GetMedium()->GetErrorCode(); + return lError; +} + +void SfxObjectShell::ResetError() +{ + pImpl->lErr=ERRCODE_NONE; + SfxMedium * pMed = GetMedium(); + if( pMed ) + pMed->ResetError(); +} + +void SfxObjectShell::EnableSetModified( bool bEnable ) +{ + SAL_INFO_IF( bEnable == pImpl->m_bEnableSetModified, "sfx", "SFX_PERSIST: EnableSetModified 2x called with the same value" ); + pImpl->m_bEnableSetModified = bEnable; +} + + +bool SfxObjectShell::IsEnableSetModified() const +{ + return pImpl->m_bEnableSetModified && !IsReadOnly(); +} + + +bool SfxObjectShell::IsModified() const +{ + if ( pImpl->m_bIsModified ) + return true; + + if ( !pImpl->m_xDocStorage.is() || IsReadOnly() ) + { + // if the document still has no storage and is not set to be modified explicitly it is not modified + // a readonly document is also not modified + + return false; + } + + if (pImpl->mxObjectContainer) + { + const uno::Sequence < OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames(); + for ( const auto& rName : aNames ) + { + uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObjectContainer().GetEmbeddedObject( rName ); + OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!" ); + if ( xObj.is() ) + { + try + { + sal_Int32 nState = xObj->getCurrentState(); + if ( nState != embed::EmbedStates::LOADED ) + { + uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); + if ( xModifiable.is() && xModifiable->isModified() ) + return true; + } + } + catch( uno::Exception& ) + {} + } + } + } + + return false; +} + + +void SfxObjectShell::SetModified( bool bModifiedP ) +{ + SAL_INFO_IF( !bModifiedP && !IsEnableSetModified(), "sfx", + "SFX_PERSIST: SetModified( sal_False ), although IsEnableSetModified() == sal_False" ); + + if( !IsEnableSetModified() ) + return; + + if( pImpl->m_bIsModified != bModifiedP ) + { + pImpl->m_bIsModified = bModifiedP; + ModifyChanged(); + } +} + + +void SfxObjectShell::ModifyChanged() +{ + if ( pImpl->bClosing ) + // SetModified dispose of the models! + return; + + + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + pViewFrame->GetBindings().Invalidate( SID_SAVEDOCS ); + + Invalidate( SID_SIGNATURE ); + Invalidate( SID_MACRO_SIGNATURE ); + Broadcast( SfxHint( SfxHintId::TitleChanged ) ); // xmlsec05, signed state might change in title... + + SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::ModifyChanged, GlobalEventConfig::GetEventName(GlobalEventId::MODIFYCHANGED), this ) ); +} + + +bool SfxObjectShell::IsReadOnlyUI() const + +/* [Description] + + Returns sal_True if the document for the UI is treated as r/o. This is + regardless of the actual r/o, which can be checked with <IsReadOnly()>. +*/ + +{ + return pImpl->bReadOnlyUI; +} + + +bool SfxObjectShell::IsReadOnlyMedium() const + +/* [Description] + + Returns sal_True when the medium is r/o, for instance when opened as r/o. +*/ + +{ + if ( !pMedium ) + return true; + return pMedium->IsReadOnly(); +} + +bool SfxObjectShell::IsOriginallyReadOnlyMedium() const +{ + return pMedium == nullptr || pMedium->IsOriginallyReadOnly(); +} + +bool SfxObjectShell::IsOriginallyLoadedReadOnlyMedium() const +{ + return pMedium != nullptr && pMedium->IsOriginallyLoadedReadOnly(); +} + + +void SfxObjectShell::SetReadOnlyUI( bool bReadOnly ) + +/* [Description] + + Turns the document in a r/o and r/w state respectively without reloading + it and without changing the open mode of the medium. +*/ + +{ + if ( bReadOnly != pImpl->bReadOnlyUI ) + { + pImpl->bReadOnlyUI = bReadOnly; + Broadcast( SfxHint(SfxHintId::ModeChanged) ); + } +} + + +void SfxObjectShell::SetReadOnly() +{ + // Let the document be completely readonly, means that the + // medium open mode is adjusted accordingly, and the write lock + // on the file is removed. + + if ( !pMedium || IsReadOnlyMedium() ) + return; + + bool bWasROUI = IsReadOnly(); + + pMedium->UnlockFile( false ); + + // the storage-based mediums are already based on the temporary file + // so UnlockFile has already closed the locking stream + if ( !pMedium->HasStorage_Impl() && IsLoadingFinished() ) + pMedium->CloseInStream(); + + pMedium->SetOpenMode( SFX_STREAM_READONLY, true ); + pMedium->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) ); + + if ( !bWasROUI ) + Broadcast( SfxHint(SfxHintId::ModeChanged) ); +} + + +bool SfxObjectShell::IsReadOnly() const +{ + return pImpl->bReadOnlyUI || pMedium == nullptr; +} + + +bool SfxObjectShell::IsInModalMode() const +{ + return pImpl->bModalMode || pImpl->bRunningMacro; +} + +bool SfxObjectShell::AcceptStateUpdate() const +{ + return !IsInModalMode(); +} + + +void SfxObjectShell::SetMacroMode_Impl( bool bModal ) +{ + if ( !pImpl->bRunningMacro != !bModal ) + { + pImpl->bRunningMacro = bModal; + Broadcast( SfxHint( SfxHintId::ModeChanged ) ); + } +} + + +void SfxObjectShell::SetModalMode_Impl( bool bModal ) +{ + // Broadcast only if modified, or otherwise it will possibly go into + // an endless loop + if ( pImpl->bModalMode == bModal ) + return; + + // Central count + sal_uInt16 &rDocModalCount = SfxGetpApp()->Get_Impl()->nDocModalMode; + if ( bModal ) + ++rDocModalCount; + else + --rDocModalCount; + + // Switch + pImpl->bModalMode = bModal; + Broadcast( SfxHint( SfxHintId::ModeChanged ) ); +} + +#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT + +bool SfxObjectShell::SwitchToShared( bool bShared, bool bSave ) +{ + bool bResult = true; + + if ( bShared != IsDocShared() ) + { + OUString aOrigURL = GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ); + + if ( aOrigURL.isEmpty() && bSave ) + { + // this is a new document, let it be stored before switching to the shared mode; + // the storing should be done without shared flag, since it is possible that the + // target location does not allow to create sharing control file; + // the shared flag will be set later after creation of sharing control file + SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( this ); + + if ( pViewFrame ) + { + // TODO/LATER: currently the application guards against the reentrance problem + const SfxPoolItem* pItem = pViewFrame->GetBindings().ExecuteSynchron( HasName() ? SID_SAVEDOC : SID_SAVEASDOC ); + const SfxBoolItem* pResult = dynamic_cast<const SfxBoolItem*>( pItem ); + bResult = ( pResult && pResult->GetValue() ); + if ( bResult ) + aOrigURL = GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + } + + bool bOldValue = HasSharedXMLFlagSet(); + SetSharedXMLFlag( bShared ); + + bool bRemoveEntryOnError = false; + if ( bResult && bShared ) + { + try + { + ::svt::ShareControlFile aControlFile( aOrigURL ); + aControlFile.InsertOwnEntry(); + bRemoveEntryOnError = true; + } + catch( uno::Exception& ) + { + bResult = false; + } + } + + if ( bResult && bSave ) + { + SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( this ); + + if ( pViewFrame ) + { + // TODO/LATER: currently the application guards against the reentrance problem + SetModified(); // the modified flag has to be set to let the document be stored with the shared flag + try + { + // Do *not* use dispatch mechanism in this place - we don't want others (extensions etc.) to intercept this. + pImpl->pBaseModel->store(); + bResult = true; + } + catch (...) + { + bResult = false; + } + } + } + + if ( bResult ) + { + // TODO/LATER: Is it possible that the following calls fail? + if ( bShared ) + { + pImpl->m_aSharedFileURL = aOrigURL; + GetMedium()->SwitchDocumentToTempFile(); + } + else + { + const OUString aTempFileURL = pMedium->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ); + GetMedium()->SwitchDocumentToFile( GetSharedFileURL() ); + pImpl->m_aSharedFileURL.clear(); + + // now remove the temporary file the document was based on + ::utl::UCBContentHelper::Kill( aTempFileURL ); + + try + { + // aOrigURL can not be used since it contains an old value + ::svt::ShareControlFile aControlFile( GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + aControlFile.RemoveFile(); + } + catch( uno::Exception& ) + { + } + } + } + else + { + // the saving has failed! + if ( bRemoveEntryOnError ) + { + try + { + ::svt::ShareControlFile aControlFile( aOrigURL ); + aControlFile.RemoveEntry(); + } + catch( uno::Exception& ) + {} + } + + SetSharedXMLFlag( bOldValue ); + } + } + else + bResult = false; // the second switch to the same mode + + if ( bResult ) + SetTitle( "" ); + + return bResult; +} + + +void SfxObjectShell::FreeSharedFile( const OUString& aTempFileURL ) +{ + SetSharedXMLFlag( false ); + + if ( !IsDocShared() || aTempFileURL.isEmpty() + || ::utl::UCBContentHelper::EqualURLs( aTempFileURL, GetSharedFileURL() ) ) + return; + + if ( pImpl->m_bAllowShareControlFileClean ) + { + try + { + ::svt::ShareControlFile aControlFile( GetSharedFileURL() ); + aControlFile.RemoveEntry(); + } + catch( uno::Exception& ) + { + } + } + + // the cleaning is forbidden only once + pImpl->m_bAllowShareControlFileClean = true; + + // now remove the temporary file the document is based currently on + ::utl::UCBContentHelper::Kill( aTempFileURL ); + + pImpl->m_aSharedFileURL.clear(); +} + + +void SfxObjectShell::DoNotCleanShareControlFile() +{ + pImpl->m_bAllowShareControlFileClean = false; +} + + +void SfxObjectShell::SetSharedXMLFlag( bool bFlag ) const +{ + pImpl->m_bSharedXMLFlag = bFlag; +} + + +bool SfxObjectShell::HasSharedXMLFlagSet() const +{ + return pImpl->m_bSharedXMLFlag; +} + +#endif + +bool SfxObjectShell::IsDocShared() const +{ +#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT + return ( !pImpl->m_aSharedFileURL.isEmpty() ); +#else + return false; +#endif +} + + +OUString SfxObjectShell::GetSharedFileURL() const +{ +#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT + return pImpl->m_aSharedFileURL; +#else + return OUString(); +#endif +} + +Size SfxObjectShell::GetFirstPageSize() const +{ + return GetVisArea(ASPECT_THUMBNAIL).GetSize(); +} + + +IndexBitSet& SfxObjectShell::GetNoSet_Impl() +{ + return pImpl->aBitSet; +} + + +// changes the title of the document + +void SfxObjectShell::SetTitle +( + const OUString& rTitle // the new Document Title +) + +/* [Description] + + With this method, the title of the document can be set. + This corresponds initially to the full file name. A setting of the + title does not affect the file name, but it will be shown in the + Caption-Bars of the MDI-window. +*/ + +{ + + // Nothing to do? + if ( ( ( HasName() && pImpl->aTitle == rTitle ) + || ( !HasName() && GetTitle() == rTitle ) ) + && !IsDocShared() ) + return; + + SfxApplication *pSfxApp = SfxGetpApp(); + + // If possible release the unnamed number. + if ( pImpl->bIsNamedVisible && USHRT_MAX != pImpl->nVisualDocumentNumber ) + { + pSfxApp->ReleaseIndex(pImpl->nVisualDocumentNumber); + pImpl->bIsNamedVisible = false; + } + + // Set Title + pImpl->aTitle = rTitle; + + // Notification + if ( GetMedium() ) + { + SfxShell::SetName( GetTitle(SFX_TITLE_APINAME) ); + Broadcast( SfxHint(SfxHintId::TitleChanged) ); + } +} + + + +OUString SfxObjectShell::GetTitle( sal_uInt16 nMaxLength ) const + +/* [Description] + + Returns the title or logical file name of the document, depending on the + 'nMaxLength'. + + If the file name with path is used, the Name shortened by replacing one or + more directory names with "...", URLs are currently always returned + in complete form. +*/ + +{ + SfxMedium *pMed = GetMedium(); + if ( IsLoading() ) + return OUString(); + + // Create Title? + if ( SFX_TITLE_DETECT == nMaxLength && pImpl->aTitle.isEmpty() ) + { + static bool bRecur = false; + if ( bRecur ) + return "-not available-"; + bRecur = true; + + OUString aTitle; + + if ( pMed ) + { + const SfxStringItem* pNameItem = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_DOCINFO_TITLE, false); + if ( pNameItem ) + aTitle = pNameItem->GetValue(); + } + + if ( aTitle.isEmpty() ) + aTitle = GetTitle( SFX_TITLE_FILENAME ); + + bRecur = false; + return aTitle; + } + + if (SFX_TITLE_APINAME == nMaxLength ) + return GetAPIName(); + + // Picklist/Caption is mapped + if ( pMed && ( nMaxLength == SFX_TITLE_CAPTION || nMaxLength == SFX_TITLE_PICKLIST ) ) + { + // If a specific title was given at open: + // important for URLs: use INetProtocol::File for which the set title is not + // considered. (See below, analysis of aTitleMap_Impl) + const SfxStringItem* pNameItem = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_DOCINFO_TITLE, false); + if ( pNameItem ) + return pNameItem->GetValue(); + } + + // Still unnamed? + DBG_ASSERT( !HasName() || pMed, "HasName() but no Medium?!?" ); + if ( !HasName() || !pMed ) + { + // Title already set? + if ( !pImpl->aTitle.isEmpty() ) + return pImpl->aTitle; + + // must it be numbered? + const OUString aNoName(SfxResId(STR_NONAME)); + if (pImpl->bIsNamedVisible) + { + // Append number + return aNoName + " " + OUString::number(pImpl->nVisualDocumentNumber); + } + + // Document called "Untitled" for the time being + return aNoName; + } + assert(pMed); + + const INetURLObject aURL( IsDocShared() ? GetSharedFileURL() : GetMedium()->GetName() ); + if ( nMaxLength > SFX_TITLE_CAPTION && nMaxLength <= SFX_TITLE_HISTORY ) + { + sal_uInt16 nRemote; + if (aURL.GetProtocol() == INetProtocol::File) + nRemote = 0; + else + nRemote = 1; + nMaxLength = aTitleMap_Impl[nMaxLength-SFX_TITLE_CAPTION][nRemote]; + } + + // Local file? + if ( aURL.GetProtocol() == INetProtocol::File ) + { + if ( nMaxLength == SFX_TITLE_FULLNAME ) + return aURL.HasMark() ? INetURLObject( aURL.GetURLNoMark() ).PathToFileName() : aURL.PathToFileName(); + if ( nMaxLength == SFX_TITLE_FILENAME ) + return aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset); + if ( pImpl->aTitle.isEmpty() ) + pImpl->aTitle = aURL.getBase( INetURLObject::LAST_SEGMENT, + true, INetURLObject::DecodeMechanism::WithCharset ); + } + else + { + if ( nMaxLength >= SFX_TITLE_MAXLEN ) + { + const OUString aComplete( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if( aComplete.getLength() > nMaxLength ) + return OUString::Concat("...") + aComplete.subView( aComplete.getLength() - nMaxLength + 3, nMaxLength - 3 ); + return aComplete; + } + if ( nMaxLength == SFX_TITLE_FILENAME ) + { + const OUString aName = INetURLObject::decode( aURL.GetBase(), INetURLObject::DecodeMechanism::WithCharset ); + return aName.isEmpty() ? aURL.GetURLNoPass() : aName; + } + if ( nMaxLength == SFX_TITLE_FULLNAME ) + return aURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + + // Generate Title from file name if possible + if ( pImpl->aTitle.isEmpty() ) + pImpl->aTitle = aURL.GetBase(); + + // workaround for the case when the name can not be retrieved from URL by INetURLObject + if ( pImpl->aTitle.isEmpty() ) + pImpl->aTitle = aURL.GetMainURL( INetURLObject::DecodeMechanism::WithCharset ); + } + + // Complete Title + return pImpl->aTitle; +} + + +void SfxObjectShell::InvalidateName() + +/* [Description] + + Returns the title of the new document, DocInfo-Title or + File name. Is required for loading from template or SaveAs. +*/ + +{ + pImpl->aTitle.clear(); + SetName( GetTitle( SFX_TITLE_APINAME ) ); + + Broadcast( SfxHint(SfxHintId::TitleChanged) ); +} + + +void SfxObjectShell::SetNamedVisibility_Impl() +{ + if ( !pImpl->bIsNamedVisible ) + { + pImpl->bIsNamedVisible = true; + if ( !HasName() && USHRT_MAX == pImpl->nVisualDocumentNumber && pImpl->aTitle.isEmpty() ) + { + pImpl->nVisualDocumentNumber = SfxGetpApp()->GetFreeIndex(); + Broadcast( SfxHint(SfxHintId::TitleChanged) ); + } + } + + SetName( GetTitle(SFX_TITLE_APINAME) ); +} + +void SfxObjectShell::SetNoName() +{ + bHasName = false; + GetModel()->attachResource( OUString(), GetModel()->getArgs() ); +} + + +SfxProgress* SfxObjectShell::GetProgress() const +{ + return pImpl->pProgress; +} + + +void SfxObjectShell::SetProgress_Impl +( + SfxProgress *pProgress /* to started <SfxProgress> or 0, + if the progress is to be reset */ +) + +/* [Description] + + Internal method to set or reset the Progress modes for + SfxObjectShell. +*/ + +{ + DBG_ASSERT( ( !pImpl->pProgress && pProgress ) || + ( pImpl->pProgress && !pProgress ), + "Progress activation/deactivation mismatch" ); + pImpl->pProgress = pProgress; +} + + +void SfxObjectShell::PostActivateEvent_Impl( SfxViewFrame const * pFrame ) +{ + SfxApplication* pSfxApp = SfxGetpApp(); + if ( pSfxApp->IsDowning() || IsLoading() || !pFrame || pFrame->GetFrame().IsClosing_Impl() ) + return; + + const SfxBoolItem* pHiddenItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_HIDDEN, false); + if ( !pHiddenItem || !pHiddenItem->GetValue() ) + { + SfxEventHintId nId = pImpl->nEventId; + pImpl->nEventId = SfxEventHintId::NONE; + if ( nId == SfxEventHintId::OpenDoc ) + pSfxApp->NotifyEvent(SfxViewEventHint( nId, GlobalEventConfig::GetEventName(GlobalEventId::OPENDOC), this, pFrame->GetFrame().GetController() ), false); + else if (nId == SfxEventHintId::CreateDoc ) + pSfxApp->NotifyEvent(SfxViewEventHint( nId, GlobalEventConfig::GetEventName(GlobalEventId::CREATEDOC), this, pFrame->GetFrame().GetController() ), false); + } +} + + +void SfxObjectShell::SetActivateEvent_Impl(SfxEventHintId nId ) +{ + pImpl->nEventId = nId; +} + +bool SfxObjectShell::IsAutoLoadLocked() const + +/* Returns whether an Autoload is allowed to be executed. Before the + surrounding FrameSet of the AutoLoad is also taken into account as well. +*/ + +{ + return !IsReadOnly(); +} + + +void SfxObjectShell::BreakMacroSign_Impl( bool bBreakMacroSign ) +{ + pImpl->m_bMacroSignBroken = bBreakMacroSign; +} + + +void SfxObjectShell::CheckSecurityOnLoading_Impl() +{ + // make sure LO evaluates the macro signatures, so it can be preserved + GetScriptingSignatureState(); + + uno::Reference< task::XInteractionHandler > xInteraction; + if ( GetMedium() ) + xInteraction = GetMedium()->GetInteractionHandler(); + + // check if there is a broken signature... + CheckForBrokenDocSignatures_Impl(); + + CheckEncryption_Impl( xInteraction ); + + // check macro security + const bool bHasValidContentSignature = HasValidSignatures(); + pImpl->aMacroMode.checkMacrosOnLoading( xInteraction, bHasValidContentSignature ); +} + + +void SfxObjectShell::CheckEncryption_Impl( const uno::Reference< task::XInteractionHandler >& xHandler ) +{ + OUString aVersion; + bool bIsEncrypted = false; + bool bHasNonEncrypted = false; + + try + { + uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW ); + xPropSet->getPropertyValue("Version") >>= aVersion; + xPropSet->getPropertyValue("HasEncryptedEntries") >>= bIsEncrypted; + xPropSet->getPropertyValue("HasNonEncryptedEntries") >>= bHasNonEncrypted; + } + catch( uno::Exception& ) + { + } + + if ( aVersion.compareTo( ODFVER_012_TEXT ) < 0 ) + return; + + // this is ODF1.2 or later + if ( !(bIsEncrypted && bHasNonEncrypted) ) + return; + + if ( !pImpl->m_bIncomplEncrWarnShown ) + { + // this is an encrypted document with nonencrypted streams inside, show the warning + css::task::ErrorCodeRequest aErrorCode; + aErrorCode.ErrCode = sal_uInt32(ERRCODE_SFX_INCOMPLETE_ENCRYPTION); + + SfxMedium::CallApproveHandler( xHandler, uno::Any( aErrorCode ), false ); + pImpl->m_bIncomplEncrWarnShown = true; + } + + // broken signatures imply no macro execution at all + pImpl->aMacroMode.disallowMacroExecution(); +} + + +void SfxObjectShell::CheckForBrokenDocSignatures_Impl() +{ + SignatureState nSignatureState = GetDocumentSignatureState(); + bool bSignatureBroken = ( nSignatureState == SignatureState::BROKEN ); + if ( !bSignatureBroken ) + return; + + // broken signatures imply no macro execution at all + pImpl->aMacroMode.disallowMacroExecution(); +} + + +void SfxObjectShell::SetAutoLoad( + const INetURLObject& rUrl, sal_uInt32 nTime, bool bReload ) +{ + pImpl->pReloadTimer.reset(); + if ( bReload ) + { + pImpl->pReloadTimer.reset(new AutoReloadTimer_Impl( + rUrl.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ), + nTime, this )); + pImpl->pReloadTimer->Start(); + } +} + +void SfxObjectShell::SetLoading(SfxLoadedFlags nFlags) +{ + pImpl->nLoadedFlags = nFlags; +} + +bool SfxObjectShell::IsLoadingFinished() const +{ + return ( pImpl->nLoadedFlags == SfxLoadedFlags::ALL ); +} + +void SfxObjectShell::InitOwnModel_Impl() +{ + if ( pImpl->bModelInitialized ) + return; + + const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_DOC_SALVAGE, false); + if ( pSalvageItem ) + { + pImpl->aTempName = pMedium->GetPhysicalName(); + pMedium->GetItemSet()->ClearItem( SID_DOC_SALVAGE ); + pMedium->GetItemSet()->ClearItem( SID_FILE_NAME ); + pMedium->GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, pMedium->GetOrigURL() ) ); + } + else + { + pMedium->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); + pMedium->GetItemSet()->ClearItem( SID_DOCUMENT ); + } + + pMedium->GetItemSet()->ClearItem( SID_REFERER ); + uno::Reference< frame::XModel > xModel = GetModel(); + if ( xModel.is() ) + { + SfxItemSet *pSet = GetMedium()->GetItemSet(); + if ( !GetMedium()->IsReadOnly() ) + pSet->ClearItem( SID_INPUTSTREAM ); + uno::Sequence< beans::PropertyValue > aArgs; + TransformItems( SID_OPENDOC, *pSet, aArgs ); + xModel->attachResource( GetMedium()->GetOrigURL(), aArgs ); + impl_addToModelCollection(xModel); + } + + pImpl->bModelInitialized = true; +} + +void SfxObjectShell::FinishedLoading( SfxLoadedFlags nFlags ) +{ + bool bSetModifiedTRUE = false; + const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_DOC_SALVAGE, false); + if( ( nFlags & SfxLoadedFlags::MAINDOCUMENT ) && !(pImpl->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) + && !(pImpl->nFlagsInProgress & SfxLoadedFlags::MAINDOCUMENT )) + { + pImpl->nFlagsInProgress |= SfxLoadedFlags::MAINDOCUMENT; + static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes())->SetAttributes(); + + if ( ( GetModifyPasswordHash() || GetModifyPasswordInfo().hasElements() ) && !IsModifyPasswordEntered() ) + SetReadOnly(); + + // Salvage + if ( pSalvageItem ) + bSetModifiedTRUE = true; + + if ( !IsEnableSetModified() ) + EnableSetModified(); + + if( !bSetModifiedTRUE && IsEnableSetModified() ) + SetModified( false ); + + CheckSecurityOnLoading_Impl(); + + bHasName = true; // the document is loaded, so the name should already available + GetTitle( SFX_TITLE_DETECT ); + InitOwnModel_Impl(); + pImpl->nFlagsInProgress &= ~SfxLoadedFlags::MAINDOCUMENT; + } + + if( ( nFlags & SfxLoadedFlags::IMAGES ) && !(pImpl->nLoadedFlags & SfxLoadedFlags::IMAGES ) + && !(pImpl->nFlagsInProgress & SfxLoadedFlags::IMAGES )) + { + pImpl->nFlagsInProgress |= SfxLoadedFlags::IMAGES; + uno::Reference<document::XDocumentProperties> xDocProps( + getDocProperties()); + const OUString url(xDocProps->getAutoloadURL()); + sal_Int32 delay(xDocProps->getAutoloadSecs()); + SetAutoLoad( INetURLObject(url), delay * 1000, + (delay > 0) || !url.isEmpty() ); + if( !bSetModifiedTRUE && IsEnableSetModified() ) + SetModified( false ); + Invalidate( SID_SAVEASDOC ); + pImpl->nFlagsInProgress &= ~SfxLoadedFlags::IMAGES; + } + + pImpl->nLoadedFlags |= nFlags; + + if ( pImpl->nFlagsInProgress != SfxLoadedFlags::NONE ) + return; + + // in case of reentrance calls the first called FinishedLoading() call on the stack + // should do the notification, in result the notification is done when all the FinishedLoading() calls are finished + + if ( bSetModifiedTRUE ) + SetModified(); + else + SetModified( false ); + + if ( (pImpl->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) && (pImpl->nLoadedFlags & SfxLoadedFlags::IMAGES ) ) + { + const SfxBoolItem* pTemplateItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_TEMPLATE, false); + bool bTemplate = pTemplateItem && pTemplateItem->GetValue(); + + // closing the streams on loading should be under control of SFX! + DBG_ASSERT( pMedium->IsOpen(), "Don't close the medium when loading documents!" ); + + if ( bTemplate ) + { + TemplateDisconnectionAfterLoad(); + } + else + { + // if a readonly medium has storage then it's stream is already based on temporary file + if( !(pMedium->GetOpenMode() & StreamMode::WRITE) && !pMedium->HasStorage_Impl() ) + // don't lock file opened read only + pMedium->CloseInStream(); + } + } + + SetInitialized_Impl( false ); + + // Title is not available until loading has finished + Broadcast( SfxHint( SfxHintId::TitleChanged ) ); + if ( pImpl->nEventId != SfxEventHintId::NONE ) + PostActivateEvent_Impl(SfxViewFrame::GetFirst(this)); +} + +void SfxObjectShell::TemplateDisconnectionAfterLoad() +{ + // document is created from a template + //TODO/LATER: should the templates always be XML docs! + + SfxMedium* pTmpMedium = pMedium; + if ( !pTmpMedium ) + return; + + const OUString aName( pTmpMedium->GetName() ); + const SfxStringItem* pTemplNamItem = SfxItemSet::GetItem<SfxStringItem>(pTmpMedium->GetItemSet(), SID_TEMPLATE_NAME, false); + OUString aTemplateName; + if ( pTemplNamItem ) + aTemplateName = pTemplNamItem->GetValue(); + else + { + // !TODO/LATER: what's this?! + // Interactive ( DClick, Contextmenu ) no long name is included + aTemplateName = getDocProperties()->getTitle(); + if ( aTemplateName.isEmpty() ) + { + INetURLObject aURL( aName ); + aURL.CutExtension(); + aTemplateName = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset ); + } + } + + // set medium to noname + pTmpMedium->SetName( OUString(), true ); + pTmpMedium->Init_Impl(); + + // drop resource + SetNoName(); + InvalidateName(); + + if( IsPackageStorageFormat_Impl( *pTmpMedium ) ) + { + // untitled document must be based on temporary storage + // the medium should not dispose the storage in this case + uno::Reference < embed::XStorage > xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage(); + GetStorage()->copyToStorage( xTmpStor ); + + // the medium should disconnect from the original location + // the storage should not be disposed since the document is still + // based on it, but in DoSaveCompleted it will be disposed + pTmpMedium->CanDisposeStorage_Impl( false ); + pTmpMedium->Close(); + + // setting the new storage the medium will be based on + pTmpMedium->SetStorage_Impl( xTmpStor ); + + pMedium = nullptr; + bool ok = DoSaveCompleted( pTmpMedium ); + assert(pMedium != nullptr); + if( ok ) + { + const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_DOC_SALVAGE, false); + bool bSalvage = pSalvageItem != nullptr; + + if ( !bSalvage ) + { + // some further initializations for templates + SetTemplate_Impl( aName, aTemplateName, this ); + } + + // the medium should not dispose the storage, DoSaveCompleted() has let it to do so + pTmpMedium->CanDisposeStorage_Impl( false ); + } + else + { + SetError(ERRCODE_IO_GENERAL); + } + } + else + { + // some further initializations for templates + SetTemplate_Impl( aName, aTemplateName, this ); + pTmpMedium->CreateTempFile(); + } + + // templates are never readonly + pTmpMedium->GetItemSet()->ClearItem( SID_DOC_READONLY ); + pTmpMedium->SetOpenMode( SFX_STREAM_READWRITE, true ); + + // notifications about possible changes in readonly state and document info + Broadcast( SfxHint(SfxHintId::ModeChanged) ); + + // created untitled document can't be modified + SetModified( false ); +} + + +bool SfxObjectShell::IsLoading() const +/* [Description] + + Has FinishedLoading been called? +*/ +{ + return !( pImpl->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ); +} + + +void SfxObjectShell::CancelTransfers() +/* [Description] + + Here can Transfers get canceled, which were not registered + by RegisterTransfer. +*/ +{ + if( ( pImpl->nLoadedFlags & SfxLoadedFlags::ALL ) != SfxLoadedFlags::ALL ) + { + pImpl->bIsAbortingImport = true; + if( IsLoading() ) + FinishedLoading(); + } +} + + +AutoReloadTimer_Impl::AutoReloadTimer_Impl( + const OUString& rURL, sal_uInt32 nTime, SfxObjectShell* pSh ) + : Timer("sfx2 AutoReloadTimer_Impl"), aUrl( rURL ), pObjSh( pSh ) +{ + SetTimeout( nTime ); +} + + +void AutoReloadTimer_Impl::Invoke() +{ + SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pObjSh ); + + if ( pFrame ) + { + // Not possible/meaningful at the moment? + if ( !pObjSh->CanReload_Impl() || pObjSh->IsAutoLoadLocked() || Application::IsUICaptured() ) + { + // Allow a retry + Start(); + return; + } + + SfxAllItemSet aSet( SfxGetpApp()->GetPool() ); + aSet.Put( SfxBoolItem( SID_AUTOLOAD, true ) ); + if ( !aUrl.isEmpty() ) + aSet.Put( SfxStringItem( SID_FILE_NAME, aUrl ) ); + if (pObjSh->HasName()) { + aSet.Put( + SfxStringItem(SID_REFERER, pObjSh->GetMedium()->GetName())); + } + SfxRequest aReq( SID_RELOAD, SfxCallMode::SLOT, aSet ); + // this will delete this + pObjSh->Get_Impl()->pReloadTimer.reset(); + pFrame->ExecReload_Impl( aReq ); + return; + } + + // this will delete this + pObjSh->Get_Impl()->pReloadTimer.reset(); +} + +SfxModule* SfxObjectShell::GetModule() const +{ + return GetFactory().GetModule(); +} + +ErrCode SfxObjectShell::CallBasic( std::u16string_view rMacro, + std::u16string_view rBasic, SbxArray* pArgs, + SbxValue* pRet ) +{ + SfxApplication* pApp = SfxGetpApp(); + if( pApp->GetName() != rBasic ) + { + if ( !AdjustMacroMode() ) + return ERRCODE_IO_ACCESSDENIED; + } + + BasicManager *pMgr = GetBasicManager(); + if( pApp->GetName() == rBasic ) + pMgr = SfxApplication::GetBasicManager(); + ErrCode nRet = SfxApplication::CallBasic( OUString(rMacro), pMgr, pArgs, pRet ); + return nRet; +} + +bool SfxObjectShell::isScriptAccessAllowed( const Reference< XInterface >& _rxScriptContext ) +{ + try + { + Reference< XEmbeddedScripts > xScripts( _rxScriptContext, UNO_QUERY ); + if ( !xScripts.is() ) + { + Reference< XScriptInvocationContext > xContext( _rxScriptContext, UNO_QUERY_THROW ); + xScripts.set( xContext->getScriptContainer(), UNO_SET_THROW ); + } + + return xScripts->getAllowMacroExecution(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("sfx.doc"); + } + return false; +} + +// don't allow LibreLogo to be used with our mouseover/etc dom-alike events +bool SfxObjectShell::UnTrustedScript(const OUString& rScriptURL) +{ + if (!rScriptURL.startsWith("vnd.sun.star.script:")) + return false; + + // ensure URL Escape Codes are decoded + css::uno::Reference<css::uri::XUriReference> uri( + css::uri::UriReferenceFactory::create(comphelper::getProcessComponentContext())->parse(rScriptURL)); + css::uno::Reference<css::uri::XVndSunStarScriptUrl> sfUri(uri, css::uno::UNO_QUERY); + + if (!sfUri.is()) + return false; + + // pyuno encodes path separator as | + OUString sScript = sfUri->getName().replace('|', '/'); + + // check if any path portion matches LibreLogo and ban it if it does + sal_Int32 nIndex = 0; + do + { + OUString aToken = sScript.getToken(0, '/', nIndex); + if (aToken.startsWithIgnoreAsciiCase("LibreLogo") || aToken.indexOf('~') != -1) + { + return true; + } + } + while (nIndex >= 0); + + return false; +} + +ErrCode SfxObjectShell::CallXScript( const Reference< XInterface >& _rxScriptContext, const OUString& _rScriptURL, + const Sequence< Any >& aParams, Any& aRet, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam, bool bRaiseError, const css::uno::Any* pCaller ) +{ + SAL_INFO("sfx", "in CallXScript" ); + ErrCode nErr = ERRCODE_NONE; + + bool bCaughtException = false; + Any aException; + try + { + if (!isScriptAccessAllowed(_rxScriptContext)) + return ERRCODE_IO_ACCESSDENIED; + + if ( UnTrustedScript(_rScriptURL) ) + return ERRCODE_IO_ACCESSDENIED; + + // obtain/create a script provider + Reference< provider::XScriptProvider > xScriptProvider; + Reference< provider::XScriptProviderSupplier > xSPS( _rxScriptContext, UNO_QUERY ); + if ( xSPS.is() ) + xScriptProvider.set( xSPS->getScriptProvider() ); + + if ( !xScriptProvider.is() ) + { + Reference< provider::XScriptProviderFactory > xScriptProviderFactory = + provider::theMasterScriptProviderFactory::get( ::comphelper::getProcessComponentContext() ); + xScriptProvider.set( xScriptProviderFactory->createScriptProvider( Any( _rxScriptContext ) ), UNO_SET_THROW ); + } + + // ry to protect the invocation context's undo manager (if present), just in case the script tampers with it + ::framework::DocumentUndoGuard aUndoGuard( _rxScriptContext ); + + // obtain the script, and execute it + Reference< provider::XScript > xScript( xScriptProvider->getScript( _rScriptURL ), UNO_SET_THROW ); + if ( pCaller && pCaller->hasValue() ) + { + Reference< beans::XPropertySet > xProps( xScript, uno::UNO_QUERY ); + if ( xProps.is() ) + { + Sequence< uno::Any > aArgs{ *pCaller }; + xProps->setPropertyValue("Caller", uno::Any( aArgs ) ); + } + } + aRet = xScript->invoke( aParams, aOutParamIndex, aOutParam ); + } + catch ( const uno::Exception& ) + { + aException = ::cppu::getCaughtException(); + bCaughtException = true; + nErr = ERRCODE_BASIC_INTERNAL_ERROR; + } + + if ( bCaughtException && bRaiseError ) + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + pFact->ShowAsyncScriptErrorDialog( nullptr, aException ); + } + + SAL_INFO("sfx", "leaving CallXScript" ); + return nErr; +} + +// perhaps rename to CallScript once we get rid of the existing CallScript +// and Call, CallBasic, CallStarBasic methods +ErrCode SfxObjectShell::CallXScript( const OUString& rScriptURL, + const css::uno::Sequence< css::uno::Any >& aParams, + css::uno::Any& aRet, + css::uno::Sequence< sal_Int16 >& aOutParamIndex, + css::uno::Sequence< css::uno::Any >& aOutParam, + bool bRaiseError, + const css::uno::Any* pCaller ) +{ + return CallXScript( GetModel(), rScriptURL, aParams, aRet, aOutParamIndex, aOutParam, bRaiseError, pCaller ); +} + +void SfxHeaderAttributes_Impl::SetAttributes() +{ + bAlert = true; + SvKeyValue aPair; + for( bool bCont = xIter->GetFirst( aPair ); bCont; + bCont = xIter->GetNext( aPair ) ) + SetAttribute( aPair ); +} + +void SfxHeaderAttributes_Impl::SetAttribute( const SvKeyValue& rKV ) +{ + const OUString& aValue = rKV.GetValue(); + if( rKV.GetKey().equalsIgnoreAsciiCase("refresh") && !rKV.GetValue().isEmpty() ) + { + sal_Int32 nIdx{ 0 }; + const sal_Int32 nTime{ o3tl::toInt32(o3tl::getToken(aValue, 0, ';', nIdx )) }; + const OUString aURL{ comphelper::string::strip(o3tl::getToken(aValue, 0, ';', nIdx ), ' ') }; + uno::Reference<document::XDocumentProperties> xDocProps( + pDoc->getDocProperties()); + if( aURL.startsWithIgnoreAsciiCase( "url=" ) ) + { + try { + xDocProps->setAutoloadURL( + rtl::Uri::convertRelToAbs(pDoc->GetMedium()->GetName(), aURL.copy( 4 )) ); + } catch (rtl::MalformedUriException &) { + TOOLS_WARN_EXCEPTION("sfx", ""); + } + } + try + { + xDocProps->setAutoloadSecs( nTime ); + } + catch (lang::IllegalArgumentException &) + { + // ignore + } + } + else if( rKV.GetKey().equalsIgnoreAsciiCase( "expires" ) ) + { + DateTime aDateTime( DateTime::EMPTY ); + if( INetMIMEMessage::ParseDateField( rKV.GetValue(), aDateTime ) ) + { + aDateTime.ConvertToLocalTime(); + pDoc->GetMedium()->SetExpired_Impl( aDateTime ); + } + else + { + pDoc->GetMedium()->SetExpired_Impl( Date( 1, 1, 1970 ) ); + } + } +} + +void SfxHeaderAttributes_Impl::Append( const SvKeyValue& rKV ) +{ + xIter->Append( rKV ); + if( bAlert ) SetAttribute( rKV ); +} + +SvKeyValueIterator* SfxObjectShell::GetHeaderAttributes() +{ + if( !pImpl->xHeaderAttributes.is() ) + { + DBG_ASSERT( pMedium, "No Medium" ); + pImpl->xHeaderAttributes = new SfxHeaderAttributes_Impl( this ); + } + return static_cast<SvKeyValueIterator*>( pImpl->xHeaderAttributes.get() ); +} + +void SfxObjectShell::ClearHeaderAttributesForSourceViewHack() +{ + static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes()) + ->ClearForSourceView(); +} + + +void SfxObjectShell::SetHeaderAttributesForSourceViewHack() +{ + static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes()) + ->SetAttributes(); +} + +bool SfxObjectShell::IsPreview() const +{ + if ( !pMedium ) + return false; + + bool bPreview = false; + const SfxStringItem* pFlags = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_OPTIONS, false); + if ( pFlags ) + { + // Distributed values among individual items + const OUString aFileFlags = pFlags->GetValue().toAsciiUpperCase(); + if ( -1 != aFileFlags.indexOf( 'B' ) ) + bPreview = true; + } + + if ( !bPreview ) + { + const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_PREVIEW, false); + if ( pItem ) + bPreview = pItem->GetValue(); + } + + return bPreview; +} + +void SfxObjectShell::SetWaitCursor( bool bSet ) const +{ + for( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, this ) ) + { + if ( bSet ) + pFrame->GetFrame().GetWindow().EnterWait(); + else + pFrame->GetFrame().GetWindow().LeaveWait(); + } +} + +OUString SfxObjectShell::GetAPIName() const +{ + INetURLObject aURL( IsDocShared() ? GetSharedFileURL() : GetMedium()->GetName() ); + OUString aName( aURL.GetBase() ); + if( aName.isEmpty() ) + aName = aURL.GetURLNoPass(); + if ( aName.isEmpty() ) + aName = GetTitle( SFX_TITLE_DETECT ); + return aName; +} + +void SfxObjectShell::Invalidate( sal_uInt16 nId ) +{ + for( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, this ) ) + Invalidate_Impl( pFrame->GetBindings(), nId ); +} + +bool SfxObjectShell::AdjustMacroMode() +{ + uno::Reference< task::XInteractionHandler > xInteraction; + if ( pMedium ) + xInteraction = pMedium->GetInteractionHandler(); + + CheckForBrokenDocSignatures_Impl(); + + CheckEncryption_Impl( xInteraction ); + + return pImpl->aMacroMode.adjustMacroMode( xInteraction ); +} + +css::uno::Reference<css::awt::XWindow> SfxObjectShell::GetDialogParent( SfxMedium const * pLoadingMedium ) +{ + css::uno::Reference<css::awt::XWindow> xWindow; + SfxItemSet* pSet = pLoadingMedium ? pLoadingMedium->GetItemSet() : GetMedium()->GetItemSet(); + const SfxUnoFrameItem* pUnoItem = SfxItemSet::GetItem<SfxUnoFrameItem>(pSet, SID_FILLFRAME, false); + if ( pUnoItem ) + { + const uno::Reference < frame::XFrame >& xFrame( pUnoItem->GetFrame() ); + xWindow = xFrame->getContainerWindow(); + } + + if (!xWindow) + { + SfxFrame* pFrame = nullptr; + const SfxFrameItem* pFrameItem = SfxItemSet::GetItem<SfxFrameItem>(pSet, SID_DOCFRAME, false); + if( pFrameItem && pFrameItem->GetFrame() ) + // get target frame from ItemSet + pFrame = pFrameItem->GetFrame(); + else + { + // try the current frame + SfxViewFrame* pView = SfxViewFrame::Current(); + if ( !pView || pView->GetObjectShell() != this ) + // get any visible frame + pView = SfxViewFrame::GetFirst(this); + if ( pView ) + pFrame = &pView->GetFrame(); + } + + if ( pFrame ) + { + // get topmost window + xWindow = pFrame->GetFrameInterface()->getContainerWindow(); + } + } + + if (xWindow) + { + // this frame may be invisible, show it if it is allowed + const SfxBoolItem* pHiddenItem = SfxItemSet::GetItem<SfxBoolItem>(pSet, SID_HIDDEN, false); + if ( !pHiddenItem || !pHiddenItem->GetValue() ) + { + xWindow->setVisible(true); + css::uno::Reference<css::awt::XTopWindow> xTopWindow(xWindow, uno::UNO_QUERY); + SAL_WARN_IF(!xTopWindow, "sfx.appl", "XTopWindow not available from XWindow"); + if (xTopWindow) + xTopWindow->toFront(); + } + } + + return xWindow; +} + +void SfxObjectShell::SetCreateMode_Impl( SfxObjectCreateMode nMode ) +{ + eCreateMode = nMode; +} + +bool SfxObjectShell::IsInPlaceActive() const +{ + if ( eCreateMode != SfxObjectCreateMode::EMBEDDED ) + return false; + + SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); + return pFrame && pFrame->GetFrame().IsInPlace(); +} + +bool SfxObjectShell::IsUIActive() const +{ + if ( eCreateMode != SfxObjectCreateMode::EMBEDDED ) + return false; + + SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); + return pFrame && pFrame->GetFrame().IsInPlace() && pFrame->GetFrame().GetWorkWindow_Impl()->IsVisible_Impl(); +} + +bool SfxObjectShell::UseInteractionToHandleError( + const uno::Reference< task::XInteractionHandler >& xHandler, + ErrCode nError ) +{ + bool bResult = false; + + if ( xHandler.is() ) + { + try + { + uno::Any aInteraction; + rtl::Reference<::comphelper::OInteractionAbort> pAbort = new ::comphelper::OInteractionAbort(); + rtl::Reference<::comphelper::OInteractionApprove> pApprove = new ::comphelper::OInteractionApprove(); + uno::Sequence< uno::Reference< task::XInteractionContinuation > > lContinuations{ + pAbort, pApprove + }; + + task::ErrorCodeRequest aErrorCode; + aErrorCode.ErrCode = sal_uInt32(nError); + aInteraction <<= aErrorCode; + xHandler->handle(::framework::InteractionRequest::CreateRequest (aInteraction,lContinuations)); + bResult = pAbort->wasSelected(); + } + catch( uno::Exception& ) + {} + } + + return bResult; +} + +sal_Int16 SfxObjectShell_Impl::getCurrentMacroExecMode() const +{ + sal_Int16 nImposedExecMode( MacroExecMode::NEVER_EXECUTE ); + + const SfxMedium* pMedium( rDocShell.GetMedium() ); + OSL_PRECOND( pMedium, "SfxObjectShell_Impl::getCurrentMacroExecMode: no medium!" ); + if ( pMedium ) + { + const SfxUInt16Item* pMacroModeItem = SfxItemSet::GetItem<SfxUInt16Item>(pMedium->GetItemSet(), SID_MACROEXECMODE, false); + if ( pMacroModeItem ) + nImposedExecMode = pMacroModeItem->GetValue(); + } + return nImposedExecMode; +} + +void SfxObjectShell_Impl::setCurrentMacroExecMode( sal_uInt16 nMacroMode ) +{ + const SfxMedium* pMedium( rDocShell.GetMedium() ); + OSL_PRECOND( pMedium, "SfxObjectShell_Impl::getCurrentMacroExecMode: no medium!" ); + if ( pMedium ) + { + pMedium->GetItemSet()->Put( SfxUInt16Item( SID_MACROEXECMODE, nMacroMode ) ); + } +} + +OUString SfxObjectShell_Impl::getDocumentLocation() const +{ + OUString sLocation; + + const SfxMedium* pMedium( rDocShell.GetMedium() ); + OSL_PRECOND( pMedium, "SfxObjectShell_Impl::getDocumentLocation: no medium!" ); + if ( pMedium ) + { + sLocation = pMedium->GetName(); + if ( sLocation.isEmpty() ) + { + // for documents made from a template: get the name of the template + sLocation = rDocShell.getDocProperties()->getTemplateURL(); + } + + // tdf#128006 take document base url as location + if (sLocation.isEmpty()) + sLocation = rDocShell.getDocumentBaseURL(); + } + + return sLocation; +} + +bool SfxObjectShell_Impl::documentStorageHasMacros() const +{ + return ::sfx2::DocumentMacroMode::storageHasMacros( m_xDocStorage ); +} + +bool SfxObjectShell_Impl::macroCallsSeenWhileLoading() const +{ + return rDocShell.GetMacroCallsSeenWhileLoading(); +} + +Reference< XEmbeddedScripts > SfxObjectShell_Impl::getEmbeddedDocumentScripts() const +{ + return Reference< XEmbeddedScripts >( rDocShell.GetModel(), UNO_QUERY ); +} + +SignatureState SfxObjectShell_Impl::getScriptingSignatureState() +{ + SignatureState nSignatureState( rDocShell.GetScriptingSignatureState() ); + + if ( nSignatureState != SignatureState::NOSIGNATURES && m_bMacroSignBroken ) + { + // if there is a macro signature it must be handled as broken + nSignatureState = SignatureState::BROKEN; + } + + return nSignatureState; +} + +bool SfxObjectShell_Impl::hasTrustedScriptingSignature( bool bAllowUIToAddAuthor ) +{ + bool bResult = false; + + try + { + OUString aVersion; + try + { + uno::Reference < beans::XPropertySet > xPropSet( rDocShell.GetStorage(), uno::UNO_QUERY_THROW ); + xPropSet->getPropertyValue("Version") >>= aVersion; + } + catch( uno::Exception& ) + { + } + + uno::Reference< security::XDocumentDigitalSignatures > xSigner( security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), aVersion) ); + + if ( nScriptingSignatureState == SignatureState::UNKNOWN + || nScriptingSignatureState == SignatureState::OK + || nScriptingSignatureState == SignatureState::NOTVALIDATED ) + { + const uno::Sequence< security::DocumentSignatureInformation > aInfo = rDocShell.GetDocumentSignatureInformation( true, xSigner ); + + if ( aInfo.hasElements() ) + { + if ( nScriptingSignatureState == SignatureState::UNKNOWN ) + nScriptingSignatureState = DocumentSignatures::getSignatureState(aInfo); + + if ( nScriptingSignatureState == SignatureState::OK + || nScriptingSignatureState == SignatureState::NOTVALIDATED ) + { + bResult = std::any_of(aInfo.begin(), aInfo.end(), + [&xSigner](const security::DocumentSignatureInformation& rInfo) { + return xSigner->isAuthorTrusted( rInfo.Signer ); }); + + if ( !bResult && bAllowUIToAddAuthor ) + { + uno::Reference< task::XInteractionHandler > xInteraction; + if ( rDocShell.GetMedium() ) + xInteraction = rDocShell.GetMedium()->GetInteractionHandler(); + + if ( xInteraction.is() ) + { + task::DocumentMacroConfirmationRequest aRequest; + aRequest.DocumentURL = getDocumentLocation(); + aRequest.DocumentStorage = rDocShell.GetMedium()->GetZipStorageToSign_Impl(); + aRequest.DocumentSignatureInformation = aInfo; + aRequest.DocumentVersion = aVersion; + aRequest.Classification = task::InteractionClassification_QUERY; + bResult = SfxMedium::CallApproveHandler( xInteraction, uno::Any( aRequest ), true ); + } + } + } + } + } + } + catch( uno::Exception& ) + {} + + return bResult; +} + +bool SfxObjectShell::IsContinueImportOnFilterExceptions(std::u16string_view aErrMessage) +{ + if (mbContinueImportOnFilterExceptions == undefined) + { + if (Application::GetDialogCancelMode() == DialogCancelMode::Off) + { + // Ask the user to try to continue or abort loading + OUString aMessage = SfxResId(STR_QMSG_ERROR_OPENING_FILE); + if (!aErrMessage.empty()) + aMessage += SfxResId(STR_QMSG_ERROR_OPENING_FILE_DETAILS) + aErrMessage; + aMessage += SfxResId(STR_QMSG_ERROR_OPENING_FILE_CONTINUE); + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Question, VclButtonsType::YesNo, aMessage)); + mbContinueImportOnFilterExceptions = (xBox->run() == RET_YES) ? yes : no; + } + else + mbContinueImportOnFilterExceptions = no; + } + return mbContinueImportOnFilterExceptions == yes; +} + +bool SfxObjectShell::isEditDocLocked() const +{ + Reference<XModel3> xModel = GetModel(); + if (!xModel.is()) + return false; + if (!officecfg::Office::Common::Misc::AllowEditReadonlyDocs::get()) + return true; + return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockEditDoc" } ), u"LockEditDoc", false); +} + +bool SfxObjectShell::isContentExtractionLocked() const +{ + Reference<XModel3> xModel = GetModel(); + if (!xModel.is()) + return false; + return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockContentExtraction" } ), u"LockContentExtraction", false); +} + +bool SfxObjectShell::isExportLocked() const +{ + Reference<XModel3> xModel = GetModel(); + if (!xModel.is()) + return false; + return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockExport" } ), u"LockExport", false); +} + +bool SfxObjectShell::isPrintLocked() const +{ + Reference<XModel3> xModel = GetModel(); + if (!xModel.is()) + return false; + return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockPrint" } ), u"LockPrint", false); +} + +bool SfxObjectShell::isSaveLocked() const +{ + Reference<XModel3> xModel = GetModel(); + if (!xModel.is()) + return false; + return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockSave" } ), u"LockSave", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |