Bump version to 24.04.3.4
[LibreOffice.git] / sfx2 / source / doc / objmisc.cxx
blobef7eed6b90fc8967e2164f435cb5ac9e4d94795a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <tools/inetmsg.hxx>
23 #include <comphelper/diagnose_ex.hxx>
24 #include <svl/eitem.hxx>
25 #include <svl/stritem.hxx>
26 #include <svl/intitem.hxx>
27 #include <svtools/svparser.hxx>
28 #include <cppuhelper/exc_hlp.hxx>
29 #include <sal/log.hxx>
30 #include <o3tl/string_view.hxx>
32 #include <com/sun/star/awt/XTopWindow.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
36 #include <com/sun/star/document/XDocumentProperties.hpp>
37 #include <com/sun/star/document/MacroExecMode.hpp>
38 #include <com/sun/star/document/XScriptInvocationContext.hpp>
39 #include <com/sun/star/embed/EmbedStates.hpp>
40 #include <com/sun/star/embed/XEmbeddedObject.hpp>
41 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
42 #include <com/sun/star/script/provider/XScript.hpp>
43 #include <com/sun/star/script/provider/XScriptProvider.hpp>
44 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
45 #include <com/sun/star/uri/UriReferenceFactory.hpp>
46 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
47 #include <com/sun/star/util/XModifiable.hpp>
49 #include <com/sun/star/uno/Reference.h>
50 #include <com/sun/star/uno/Any.h>
51 #include <com/sun/star/task/ErrorCodeRequest2.hpp>
53 #include <comphelper/lok.hxx>
54 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
55 #include <comphelper/processfactory.hxx>
56 #include <comphelper/string.hxx>
58 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
59 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
60 #include <com/sun/star/task/InteractionClassification.hpp>
61 #include <com/sun/star/task/XInteractionHandler.hpp>
62 #include <com/sun/star/frame/XModel.hpp>
64 #include <basic/basmgr.hxx>
65 #include <basic/sberrors.hxx>
66 #include <utility>
67 #include <vcl/weld.hxx>
68 #include <basic/sbx.hxx>
69 #include <svtools/sfxecode.hxx>
71 #include <unotools/mediadescriptor.hxx>
72 #include <unotools/ucbhelper.hxx>
73 #include <tools/urlobj.hxx>
74 #include <svl/sharecontrolfile.hxx>
75 #include <rtl/uri.hxx>
76 #include <vcl/svapp.hxx>
77 #include <framework/interaction.hxx>
78 #include <framework/documentundoguard.hxx>
79 #include <comphelper/interaction.hxx>
80 #include <comphelper/storagehelper.hxx>
81 #include <comphelper/documentconstants.hxx>
82 #include <comphelper/namedvaluecollection.hxx>
83 #include <ucbhelper/simpleinteractionrequest.hxx>
84 #include <officecfg/Office/Common.hxx>
86 #include <sfx2/brokenpackageint.hxx>
87 #include <sfx2/signaturestate.hxx>
88 #include <sfx2/app.hxx>
89 #include <appdata.hxx>
90 #include <sfx2/request.hxx>
91 #include <sfx2/bindings.hxx>
92 #include <sfx2/sfxresid.hxx>
93 #include <sfx2/docfile.hxx>
94 #include <sfx2/objsh.hxx>
95 #include <objshimp.hxx>
96 #include <sfx2/event.hxx>
97 #include <sfx2/viewfrm.hxx>
98 #include <sfx2/sfxuno.hxx>
99 #include <sfx2/module.hxx>
100 #include <sfx2/docfac.hxx>
101 #include <sfx2/sfxsids.hrc>
102 #include <sfx2/strings.hrc>
103 #include <workwin.hxx>
104 #include <sfx2/sfxdlg.hxx>
105 #include <sfx2/infobar.hxx>
106 #include <sfx2/lokhelper.hxx>
107 #include <sfx2/sfxbasemodel.hxx>
108 #include <openflag.hxx>
109 #include "objstor.hxx"
110 #include <appopen.hxx>
111 #include <sfx2/viewsh.hxx>
113 #include <memory>
115 using namespace ::com::sun::star;
116 using namespace ::com::sun::star::uno;
117 using namespace ::com::sun::star::ucb;
118 using namespace ::com::sun::star::document;
119 using namespace ::com::sun::star::frame;
120 using namespace ::com::sun::star::script;
121 using namespace ::com::sun::star::script::provider;
122 using namespace ::com::sun::star::container;
124 // class SfxHeaderAttributes_Impl ----------------------------------------
126 namespace {
128 class SfxHeaderAttributes_Impl : public SvKeyValueIterator
130 private:
131 SfxObjectShell* pDoc;
132 SvKeyValueIteratorRef xIter;
133 bool bAlert;
135 public:
136 explicit SfxHeaderAttributes_Impl( SfxObjectShell* pSh ) :
137 pDoc( pSh ),
138 xIter( pSh->GetMedium()->GetHeaderAttributes_Impl() ),
139 bAlert( false ) {}
141 virtual bool GetFirst( SvKeyValue& rKV ) override { return xIter->GetFirst( rKV ); }
142 virtual bool GetNext( SvKeyValue& rKV ) override { return xIter->GetNext( rKV ); }
143 virtual void Append( const SvKeyValue& rKV ) override;
145 void ClearForSourceView() { xIter = new SvKeyValueIterator; bAlert = false; }
146 void SetAttributes();
147 void SetAttribute( const SvKeyValue& rKV );
152 sal_uInt16 const aTitleMap_Impl[3][2] =
154 // local remote
155 /* SFX_TITLE_CAPTION */ { SFX_TITLE_FILENAME, SFX_TITLE_TITLE },
156 /* SFX_TITLE_PICKLIST */ { 32, SFX_TITLE_FULLNAME },
157 /* SFX_TITLE_HISTORY */ { 32, SFX_TITLE_FULLNAME }
161 bool SfxObjectShell::IsAbortingImport() const
163 return pImpl->bIsAbortingImport;
167 uno::Reference<document::XDocumentProperties>
168 SfxObjectShell::getDocProperties() const
170 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
171 GetModel(), uno::UNO_QUERY_THROW);
172 uno::Reference<document::XDocumentProperties> xDocProps(
173 xDPS->getDocumentProperties());
174 DBG_ASSERT(xDocProps.is(),
175 "SfxObjectShell: model has no DocumentProperties");
176 return xDocProps;
180 void SfxObjectShell::DoFlushDocInfo()
185 // Note: the only thing that calls this is the modification event handler
186 // that is installed at the XDocumentProperties
187 void SfxObjectShell::FlushDocInfo()
189 if ( IsLoading() )
190 return;
192 SetModified();
193 uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
194 DoFlushDocInfo(); // call template method
195 const OUString url(xDocProps->getAutoloadURL());
196 sal_Int32 delay(xDocProps->getAutoloadSecs());
197 SetAutoLoad( INetURLObject(url), delay * 1000,
198 (delay > 0) || !url.isEmpty() );
201 void SfxObjectShell::AppendInfoBarWhenReady(const OUString& sId, const OUString& sPrimaryMessage,
202 const OUString& sSecondaryMessage,
203 InfobarType aInfobarType, bool bShowCloseButton)
205 InfobarData aInfobarData;
206 aInfobarData.msId = sId;
207 aInfobarData.msPrimaryMessage = sPrimaryMessage;
208 aInfobarData.msSecondaryMessage = sSecondaryMessage;
209 aInfobarData.maInfobarType = aInfobarType;
210 aInfobarData.mbShowCloseButton = bShowCloseButton;
211 Get_Impl()->m_aPendingInfobars.emplace_back(aInfobarData);
214 std::vector<InfobarData>& SfxObjectShell::getPendingInfobars()
216 return Get_Impl()->m_aPendingInfobars;
219 void SfxObjectShell::SetError(const ErrCodeMsg& lErr)
221 if (pImpl->lErr==ERRCODE_NONE)
223 pImpl->lErr=lErr;
227 ErrCodeMsg SfxObjectShell::GetErrorIgnoreWarning() const
229 return GetErrorCode().IgnoreWarning();
232 ErrCodeMsg SfxObjectShell::GetErrorCode() const
234 ErrCodeMsg lError=pImpl->lErr;
235 if(!lError && GetMedium())
236 lError=GetMedium()->GetErrorCode();
237 return lError;
240 void SfxObjectShell::ResetError()
242 pImpl->lErr=ERRCODE_NONE;
243 SfxMedium * pMed = GetMedium();
244 if( pMed )
245 pMed->ResetError();
248 void SfxObjectShell::EnableSetModified( bool bEnable )
250 SAL_INFO_IF( bEnable == pImpl->m_bEnableSetModified, "sfx", "SFX_PERSIST: EnableSetModified 2x called with the same value" );
251 pImpl->m_bEnableSetModified = bEnable;
255 bool SfxObjectShell::IsEnableSetModified() const
257 // tdf#146547 read-only does not prevent modified, instead try to prevent
258 // setting "internal" documents that may be displayed in some dialog but
259 // which the user didn't load or activate to modified.
260 return pImpl->m_bEnableSetModified && !IsPreview()
261 && eCreateMode != SfxObjectCreateMode::ORGANIZER
262 && eCreateMode != SfxObjectCreateMode::INTERNAL;
266 bool SfxObjectShell::IsModified() const
268 if ( pImpl->m_bIsModified )
269 return true;
271 if ( !pImpl->m_xDocStorage.is() || IsReadOnly() )
273 // if the document still has no storage and is not set to be modified explicitly it is not modified
274 // a readonly document is also not modified
276 return false;
279 if (pImpl->mxObjectContainer)
281 const uno::Sequence < OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames();
282 for ( const auto& rName : aNames )
284 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObjectContainer().GetEmbeddedObject( rName );
285 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!" );
286 if ( xObj.is() )
290 sal_Int32 nState = xObj->getCurrentState();
291 if ( nState != embed::EmbedStates::LOADED )
293 uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
294 if ( xModifiable.is() && xModifiable->isModified() )
295 return true;
298 catch( uno::Exception& )
304 return false;
308 void SfxObjectShell::SetModified( bool bModifiedP )
310 SAL_INFO_IF( !bModifiedP && !IsEnableSetModified(), "sfx",
311 "SFX_PERSIST: SetModified( sal_False ), although IsEnableSetModified() == sal_False" );
313 if( !IsEnableSetModified() )
314 return;
316 if( pImpl->m_bIsModified != bModifiedP )
318 pImpl->m_bIsModified = bModifiedP;
319 ModifyChanged();
324 void SfxObjectShell::ModifyChanged()
326 if ( pImpl->bClosing )
327 // SetModified dispose of the models!
328 return;
330 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
331 if ( pViewFrame )
332 pViewFrame->GetBindings().Invalidate( SID_SAVEDOCS );
334 Invalidate( SID_SIGNATURE );
335 Invalidate( SID_MACRO_SIGNATURE );
336 Broadcast( SfxHint( SfxHintId::TitleChanged ) ); // xmlsec05, signed state might change in title...
338 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::ModifyChanged, GlobalEventConfig::GetEventName(GlobalEventId::MODIFYCHANGED), this ) );
340 // Don't wait to get this important state via binding notification timeout.
341 if ( comphelper::LibreOfficeKit::isActive() )
343 OString aStatus = ".uno:ModifiedStatus="_ostr;
344 aStatus += IsModified() ? "true" : "false";
345 SfxLokHelper::notifyAllViews(LOK_CALLBACK_STATE_CHANGED, aStatus);
350 bool SfxObjectShell::IsReadOnlyUI() const
352 /* [Description]
354 Returns sal_True if the document for the UI is treated as r/o. This is
355 regardless of the actual r/o, which can be checked with <IsReadOnly()>.
359 return pImpl->bReadOnlyUI || SfxViewShell::IsCurrentLokViewReadOnly();
363 bool SfxObjectShell::IsReadOnlyMedium() const
365 /* [Description]
367 Returns sal_True when the medium is r/o, for instance when opened as r/o.
371 if ( !pMedium )
372 return true;
373 return pMedium->IsReadOnly();
376 bool SfxObjectShell::IsOriginallyReadOnlyMedium() const
378 return pMedium == nullptr || pMedium->IsOriginallyReadOnly();
381 bool SfxObjectShell::IsOriginallyLoadedReadOnlyMedium() const
383 return pMedium != nullptr && pMedium->IsOriginallyLoadedReadOnly();
387 void SfxObjectShell::SetReadOnlyUI( bool bReadOnly )
389 /* [Description]
391 Turns the document in a r/o and r/w state respectively without reloading
392 it and without changing the open mode of the medium.
396 if ( bReadOnly != pImpl->bReadOnlyUI )
398 pImpl->bReadOnlyUI = bReadOnly;
399 Broadcast( SfxHint(SfxHintId::ModeChanged) );
404 void SfxObjectShell::SetReadOnly()
406 // Let the document be completely readonly, means that the
407 // medium open mode is adjusted accordingly, and the write lock
408 // on the file is removed.
410 if ( !pMedium || IsReadOnlyMedium() )
411 return;
413 bool bWasROUI = IsReadOnly();
415 pMedium->UnlockFile( false );
417 // the storage-based mediums are already based on the temporary file
418 // so UnlockFile has already closed the locking stream
419 if ( !pMedium->HasStorage_Impl() && IsLoadingFinished() )
420 pMedium->CloseInStream();
422 pMedium->SetOpenMode( SFX_STREAM_READONLY, true );
423 pMedium->GetItemSet().Put( SfxBoolItem( SID_DOC_READONLY, true ) );
425 if ( !bWasROUI )
426 Broadcast( SfxHint(SfxHintId::ModeChanged) );
430 bool SfxObjectShell::IsReadOnly() const
432 return pImpl->bReadOnlyUI || pMedium == nullptr;
436 bool SfxObjectShell::IsInModalMode() const
438 return pImpl->bModalMode || pImpl->bRunningMacro;
441 bool SfxObjectShell::AcceptStateUpdate() const
443 return !IsInModalMode();
447 void SfxObjectShell::SetMacroMode_Impl( bool bModal )
449 if ( !pImpl->bRunningMacro != !bModal )
451 pImpl->bRunningMacro = bModal;
452 Broadcast( SfxHint( SfxHintId::ModeChanged ) );
457 void SfxObjectShell::SetModalMode_Impl( bool bModal )
459 // Broadcast only if modified, or otherwise it will possibly go into
460 // an endless loop
461 if ( pImpl->bModalMode == bModal )
462 return;
464 // Central count
465 sal_uInt16 &rDocModalCount = SfxGetpApp()->Get_Impl()->nDocModalMode;
466 if ( bModal )
467 ++rDocModalCount;
468 else
469 --rDocModalCount;
471 // Switch
472 pImpl->bModalMode = bModal;
473 Broadcast( SfxHint( SfxHintId::ModeChanged ) );
476 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
478 bool SfxObjectShell::SwitchToShared( bool bShared, bool bSave )
480 bool bResult = true;
482 if ( bShared != IsDocShared() )
484 OUString aOrigURL = GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE );
486 if ( aOrigURL.isEmpty() && bSave )
488 // this is a new document, let it be stored before switching to the shared mode;
489 // the storing should be done without shared flag, since it is possible that the
490 // target location does not allow to create sharing control file;
491 // the shared flag will be set later after creation of sharing control file
492 SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( this );
494 if ( pViewFrame )
496 // TODO/LATER: currently the application guards against the reentrance problem
497 const SfxPoolItemHolder aItem(pViewFrame->GetBindings().ExecuteSynchron( HasName() ? SID_SAVEDOC : SID_SAVEASDOC ));
498 const SfxBoolItem* pResult(dynamic_cast<const SfxBoolItem*>(aItem.getItem()));
499 bResult = ( pResult && pResult->GetValue() );
500 if ( bResult )
501 aOrigURL = GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE );
505 bool bOldValue = HasSharedXMLFlagSet();
506 SetSharedXMLFlag( bShared );
508 bool bRemoveEntryOnError = false;
509 if ( bResult && bShared )
513 ::svt::ShareControlFile aControlFile( aOrigURL );
514 aControlFile.InsertOwnEntry();
515 bRemoveEntryOnError = true;
517 catch( uno::Exception& )
519 bResult = false;
523 if ( bResult && bSave )
525 SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( this );
527 if ( pViewFrame )
529 // TODO/LATER: currently the application guards against the reentrance problem
530 SetModified(); // the modified flag has to be set to let the document be stored with the shared flag
533 // Do *not* use dispatch mechanism in this place - we don't want others (extensions etc.) to intercept this.
534 pImpl->pBaseModel->store();
535 bResult = true;
537 catch (...)
539 bResult = false;
544 if ( bResult )
546 // TODO/LATER: Is it possible that the following calls fail?
547 if ( bShared )
549 pImpl->m_aSharedFileURL = aOrigURL;
550 GetMedium()->SwitchDocumentToTempFile();
552 else
554 const OUString aTempFileURL = pMedium->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE );
555 GetMedium()->SwitchDocumentToFile( GetSharedFileURL() );
556 pImpl->m_aSharedFileURL.clear();
558 // now remove the temporary file the document was based on
559 ::utl::UCBContentHelper::Kill( aTempFileURL );
563 // aOrigURL can not be used since it contains an old value
564 ::svt::ShareControlFile aControlFile( GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
565 aControlFile.RemoveFile();
567 catch( uno::Exception& )
572 else
574 // the saving has failed!
575 if ( bRemoveEntryOnError )
579 ::svt::ShareControlFile aControlFile( aOrigURL );
580 aControlFile.RemoveEntry();
582 catch( uno::Exception& )
586 SetSharedXMLFlag( bOldValue );
589 else
590 bResult = false; // the second switch to the same mode
592 if ( bResult )
593 SetTitle( "" );
595 return bResult;
599 void SfxObjectShell::FreeSharedFile( const OUString& aTempFileURL )
601 SetSharedXMLFlag( false );
603 if ( !IsDocShared() || aTempFileURL.isEmpty()
604 || ::utl::UCBContentHelper::EqualURLs( aTempFileURL, GetSharedFileURL() ) )
605 return;
607 if ( pImpl->m_bAllowShareControlFileClean )
611 ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
612 aControlFile.RemoveEntry();
614 catch( uno::Exception& )
619 // the cleaning is forbidden only once
620 pImpl->m_bAllowShareControlFileClean = true;
622 // now remove the temporary file the document is based currently on
623 ::utl::UCBContentHelper::Kill( aTempFileURL );
625 pImpl->m_aSharedFileURL.clear();
629 void SfxObjectShell::DoNotCleanShareControlFile()
631 pImpl->m_bAllowShareControlFileClean = false;
635 void SfxObjectShell::SetSharedXMLFlag( bool bFlag ) const
637 pImpl->m_bSharedXMLFlag = bFlag;
641 bool SfxObjectShell::HasSharedXMLFlagSet() const
643 return pImpl->m_bSharedXMLFlag;
646 #endif
648 bool SfxObjectShell::IsDocShared() const
650 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
651 return ( !pImpl->m_aSharedFileURL.isEmpty() );
652 #else
653 return false;
654 #endif
658 OUString SfxObjectShell::GetSharedFileURL() const
660 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
661 return pImpl->m_aSharedFileURL;
662 #else
663 return OUString();
664 #endif
667 Size SfxObjectShell::GetFirstPageSize() const
669 return GetVisArea(ASPECT_THUMBNAIL).GetSize();
673 IndexBitSet& SfxObjectShell::GetNoSet_Impl()
675 return pImpl->aBitSet;
679 // changes the title of the document
681 void SfxObjectShell::SetTitle
683 const OUString& rTitle // the new Document Title
686 /* [Description]
688 With this method, the title of the document can be set.
689 This corresponds initially to the full file name. A setting of the
690 title does not affect the file name, but it will be shown in the
691 Caption-Bars of the MDI-window.
696 // Nothing to do?
697 if ( ( ( HasName() && pImpl->aTitle == rTitle )
698 || ( !HasName() && GetTitle() == rTitle ) )
699 && !IsDocShared() )
700 return;
702 SfxApplication *pSfxApp = SfxGetpApp();
704 // If possible release the unnamed number.
705 if ( pImpl->bIsNamedVisible && USHRT_MAX != pImpl->nVisualDocumentNumber )
707 pSfxApp->ReleaseIndex(pImpl->nVisualDocumentNumber);
708 pImpl->bIsNamedVisible = false;
711 // Set Title
712 pImpl->aTitle = rTitle;
714 // Notification
715 if ( GetMedium() )
717 SfxShell::SetName( GetTitle(SFX_TITLE_APINAME) );
718 Broadcast( SfxHint(SfxHintId::TitleChanged) );
724 OUString SfxObjectShell::GetTitle( sal_uInt16 nMaxLength ) const
726 /* [Description]
728 Returns the title or logical file name of the document, depending on the
729 'nMaxLength'.
731 If the file name with path is used, the Name shortened by replacing one or
732 more directory names with "...", URLs are currently always returned
733 in complete form.
737 SfxMedium *pMed = GetMedium();
738 if ( IsLoading() )
739 return OUString();
741 // Create Title?
742 if ( SFX_TITLE_DETECT == nMaxLength && pImpl->aTitle.isEmpty() )
744 static bool bRecur = false;
745 if ( bRecur )
746 return "-not available-";
747 bRecur = true;
749 OUString aTitle;
751 if ( pMed )
753 const SfxStringItem* pNameItem = pMed->GetItemSet().GetItem(SID_DOCINFO_TITLE, false);
754 if ( pNameItem )
755 aTitle = pNameItem->GetValue();
758 if ( aTitle.isEmpty() )
759 aTitle = GetTitle( SFX_TITLE_FILENAME );
761 bRecur = false;
762 return aTitle;
765 if (SFX_TITLE_APINAME == nMaxLength )
766 return GetAPIName();
768 // Picklist/Caption is mapped
769 if ( pMed && ( nMaxLength == SFX_TITLE_CAPTION || nMaxLength == SFX_TITLE_PICKLIST ) )
771 // If a specific title was given at open:
772 // important for URLs: use INetProtocol::File for which the set title is not
773 // considered. (See below, analysis of aTitleMap_Impl)
774 const SfxStringItem* pNameItem = pMed->GetItemSet().GetItem(SID_DOCINFO_TITLE, false);
775 if ( pNameItem )
776 return pNameItem->GetValue();
779 // Still unnamed?
780 DBG_ASSERT( !HasName() || pMed, "HasName() but no Medium?!?" );
781 if ( !HasName() || !pMed )
783 // Title already set?
784 if ( !pImpl->aTitle.isEmpty() )
785 return pImpl->aTitle;
787 // must it be numbered?
788 const OUString aNoName(SfxResId(STR_NONAME));
789 if (pImpl->bIsNamedVisible)
791 // Append number
792 return aNoName + " " + OUString::number(pImpl->nVisualDocumentNumber);
795 // Document called "Untitled" for the time being
796 return aNoName;
798 assert(pMed);
800 const INetURLObject aURL( IsDocShared() ? GetSharedFileURL() : GetMedium()->GetName() );
801 if ( nMaxLength > SFX_TITLE_CAPTION && nMaxLength <= SFX_TITLE_HISTORY )
803 sal_uInt16 nRemote;
804 if (aURL.GetProtocol() == INetProtocol::File)
805 nRemote = 0;
806 else
807 nRemote = 1;
808 nMaxLength = aTitleMap_Impl[nMaxLength-SFX_TITLE_CAPTION][nRemote];
811 // Local file?
812 if ( aURL.GetProtocol() == INetProtocol::File )
814 if ( nMaxLength == SFX_TITLE_FULLNAME )
815 return aURL.HasMark() ? INetURLObject( aURL.GetURLNoMark() ).PathToFileName() : aURL.PathToFileName();
816 if ( nMaxLength == SFX_TITLE_FILENAME )
817 return aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset);
818 if ( pImpl->aTitle.isEmpty() )
819 pImpl->aTitle = aURL.getBase( INetURLObject::LAST_SEGMENT,
820 true, INetURLObject::DecodeMechanism::WithCharset );
822 else
824 if ( nMaxLength >= SFX_TITLE_MAXLEN )
826 const OUString aComplete( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
827 if( aComplete.getLength() > nMaxLength )
828 return OUString::Concat("...") + aComplete.subView( aComplete.getLength() - nMaxLength + 3, nMaxLength - 3 );
829 return aComplete;
831 if ( nMaxLength == SFX_TITLE_FILENAME )
833 const OUString aName = INetURLObject::decode( aURL.GetBase(), INetURLObject::DecodeMechanism::WithCharset );
834 return aName.isEmpty() ? aURL.GetURLNoPass() : aName;
836 if ( nMaxLength == SFX_TITLE_FULLNAME )
837 return aURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
839 // Generate Title from file name if possible
840 if ( pImpl->aTitle.isEmpty() )
841 pImpl->aTitle = aURL.GetBase();
843 // workaround for the case when the name can not be retrieved from URL by INetURLObject
844 if ( pImpl->aTitle.isEmpty() )
845 pImpl->aTitle = aURL.GetMainURL( INetURLObject::DecodeMechanism::WithCharset );
848 // Complete Title
849 return pImpl->aTitle;
853 void SfxObjectShell::InvalidateName()
855 /* [Description]
857 Returns the title of the new document, DocInfo-Title or
858 File name. Is required for loading from template or SaveAs.
862 pImpl->aTitle.clear();
863 SetName( GetTitle( SFX_TITLE_APINAME ) );
865 Broadcast( SfxHint(SfxHintId::TitleChanged) );
869 void SfxObjectShell::SetNamedVisibility_Impl()
871 if ( !pImpl->bIsNamedVisible )
873 pImpl->bIsNamedVisible = true;
874 if ( !HasName() && USHRT_MAX == pImpl->nVisualDocumentNumber && pImpl->aTitle.isEmpty() )
876 pImpl->nVisualDocumentNumber = SfxGetpApp()->GetFreeIndex();
877 Broadcast( SfxHint(SfxHintId::TitleChanged) );
881 SetName( GetTitle(SFX_TITLE_APINAME) );
884 void SfxObjectShell::SetNoName()
886 bHasName = false;
887 GetModel()->attachResource( OUString(), GetModel()->getArgs() );
891 SfxProgress* SfxObjectShell::GetProgress() const
893 return pImpl->pProgress;
897 void SfxObjectShell::SetProgress_Impl
899 SfxProgress *pProgress /* to started <SfxProgress> or 0,
900 if the progress is to be reset */
903 /* [Description]
905 Internal method to set or reset the Progress modes for
906 SfxObjectShell.
910 DBG_ASSERT( ( !pImpl->pProgress && pProgress ) ||
911 ( pImpl->pProgress && !pProgress ),
912 "Progress activation/deactivation mismatch" );
913 pImpl->pProgress = pProgress;
917 void SfxObjectShell::PostActivateEvent_Impl( SfxViewFrame const * pFrame )
919 SfxApplication* pSfxApp = SfxGetpApp();
920 if ( pSfxApp->IsDowning() || IsLoading() || !pFrame || pFrame->GetFrame().IsClosing_Impl() )
921 return;
923 const SfxBoolItem* pHiddenItem = pMedium->GetItemSet().GetItem(SID_HIDDEN, false);
924 if ( !pHiddenItem || !pHiddenItem->GetValue() )
926 SfxEventHintId nId = pImpl->nEventId;
927 pImpl->nEventId = SfxEventHintId::NONE;
928 if ( nId == SfxEventHintId::OpenDoc )
929 pSfxApp->NotifyEvent(SfxViewEventHint( nId, GlobalEventConfig::GetEventName(GlobalEventId::OPENDOC), this, pFrame->GetFrame().GetController() ), false);
930 else if (nId == SfxEventHintId::CreateDoc )
931 pSfxApp->NotifyEvent(SfxViewEventHint( nId, GlobalEventConfig::GetEventName(GlobalEventId::CREATEDOC), this, pFrame->GetFrame().GetController() ), false);
936 void SfxObjectShell::SetActivateEvent_Impl(SfxEventHintId nId )
938 pImpl->nEventId = nId;
941 bool SfxObjectShell::IsAutoLoadLocked() const
943 /* Returns whether an Autoload is allowed to be executed. Before the
944 surrounding FrameSet of the AutoLoad is also taken into account as well.
948 return !IsReadOnly();
952 void SfxObjectShell::BreakMacroSign_Impl( bool bBreakMacroSign )
954 pImpl->m_bMacroSignBroken = bBreakMacroSign;
958 void SfxObjectShell::CheckSecurityOnLoading_Impl()
960 // make sure LO evaluates the macro signatures, so it can be preserved
961 GetScriptingSignatureState();
963 uno::Reference< task::XInteractionHandler > xInteraction;
964 if ( GetMedium() )
965 xInteraction = GetMedium()->GetInteractionHandler();
967 // check if there is a broken signature...
968 CheckForBrokenDocSignatures_Impl();
970 CheckEncryption_Impl( xInteraction );
972 // check macro security
973 const bool bHasValidContentSignature = HasValidSignatures();
974 const bool bHasMacros = pImpl->aMacroMode.hasMacros();
975 pImpl->aMacroMode.checkMacrosOnLoading( xInteraction, bHasValidContentSignature, bHasMacros );
976 pImpl->m_bHadCheckedMacrosOnLoad = bHasMacros;
979 bool SfxObjectShell::GetHadCheckedMacrosOnLoad() const
981 return pImpl->m_bHadCheckedMacrosOnLoad;
984 bool SfxObjectShell::AllowedLinkProtocolFromDocument(const OUString& rUrl, SfxObjectShell* pObjShell, weld::Window* pDialogParent)
986 if (!INetURLObject(rUrl).IsExoticProtocol())
987 return true;
988 // Default to ignoring exotic protocols
989 bool bAllow = false;
990 if (pObjShell)
992 // If the document had macros when loaded then follow the allowed macro-mode
993 if (pObjShell->GetHadCheckedMacrosOnLoad())
994 bAllow = pObjShell->AdjustMacroMode();
995 else // otherwise ask the user, defaulting to cancel
997 //Reuse URITools::onOpenURI warning string
998 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pDialogParent,
999 VclMessageType::Warning, VclButtonsType::YesNo,
1000 SfxResId(STR_DANGEROUS_TO_OPEN)));
1001 xQueryBox->set_primary_text(xQueryBox->get_primary_text().replaceFirst("$(ARG1)",
1002 INetURLObject::decode(rUrl, INetURLObject::DecodeMechanism::Unambiguous)));
1003 xQueryBox->set_default_response(RET_NO);
1004 bAllow = xQueryBox->run() == RET_YES;
1007 SAL_WARN_IF(!bAllow, "sfx.appl", "SfxObjectShell::AllowedLinkProtocolFromDocument ignoring: " << rUrl);
1008 return bAllow;
1011 void SfxObjectShell::CheckEncryption_Impl( const uno::Reference< task::XInteractionHandler >& xHandler )
1013 OUString aVersion;
1014 bool bIsEncrypted = false;
1015 bool bHasNonEncrypted = false;
1019 uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW );
1020 xPropSet->getPropertyValue("Version") >>= aVersion;
1021 xPropSet->getPropertyValue("HasEncryptedEntries") >>= bIsEncrypted;
1022 xPropSet->getPropertyValue("HasNonEncryptedEntries") >>= bHasNonEncrypted;
1024 catch( uno::Exception& )
1028 if ( aVersion.compareTo( ODFVER_012_TEXT ) < 0 )
1029 return;
1031 // this is ODF1.2 or later
1032 if ( !(bIsEncrypted && bHasNonEncrypted) )
1033 return;
1035 if ( !pImpl->m_bIncomplEncrWarnShown )
1037 // this is an encrypted document with nonencrypted streams inside, show the warning
1038 css::task::ErrorCodeRequest aErrorCode;
1039 aErrorCode.ErrCode = sal_uInt32(ERRCODE_SFX_INCOMPLETE_ENCRYPTION);
1041 SfxMedium::CallApproveHandler( xHandler, uno::Any( aErrorCode ), false );
1042 pImpl->m_bIncomplEncrWarnShown = true;
1045 // broken signatures imply no macro execution at all
1046 pImpl->aMacroMode.disallowMacroExecution();
1050 void SfxObjectShell::CheckForBrokenDocSignatures_Impl()
1052 SignatureState nSignatureState = GetDocumentSignatureState();
1053 bool bSignatureBroken = ( nSignatureState == SignatureState::BROKEN );
1054 if ( !bSignatureBroken )
1055 return;
1057 // broken signatures imply no macro execution at all
1058 pImpl->aMacroMode.disallowMacroExecution();
1062 void SfxObjectShell::SetAutoLoad(
1063 const INetURLObject& rUrl, sal_uInt32 nTime, bool bReload )
1065 pImpl->pReloadTimer.reset();
1066 if ( bReload )
1068 pImpl->pReloadTimer.reset(new AutoReloadTimer_Impl(
1069 rUrl.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ),
1070 nTime, this ));
1071 pImpl->pReloadTimer->Start();
1075 void SfxObjectShell::SetLoading(SfxLoadedFlags nFlags)
1077 pImpl->nLoadedFlags = nFlags;
1080 bool SfxObjectShell::IsLoadingFinished() const
1082 return ( pImpl->nLoadedFlags == SfxLoadedFlags::ALL );
1085 void SfxObjectShell::InitOwnModel_Impl()
1087 if ( pImpl->bModelInitialized )
1088 return;
1090 const SfxStringItem* pSalvageItem = pMedium->GetItemSet().GetItem(SID_DOC_SALVAGE, false);
1091 if ( pSalvageItem )
1093 pImpl->aTempName = pMedium->GetPhysicalName();
1094 pMedium->GetItemSet().ClearItem( SID_DOC_SALVAGE );
1095 pMedium->GetItemSet().ClearItem( SID_FILE_NAME );
1096 pMedium->GetItemSet().Put( SfxStringItem( SID_FILE_NAME, pMedium->GetOrigURL() ) );
1098 else
1100 pMedium->GetItemSet().ClearItem( SID_PROGRESS_STATUSBAR_CONTROL );
1101 pMedium->GetItemSet().ClearItem( SID_DOCUMENT );
1104 pMedium->GetItemSet().ClearItem( SID_REFERER );
1105 uno::Reference< frame::XModel > xModel = GetModel();
1106 if ( xModel.is() )
1108 SfxItemSet& rSet = GetMedium()->GetItemSet();
1109 if ( !GetMedium()->IsReadOnly() )
1110 rSet.ClearItem( SID_INPUTSTREAM );
1111 uno::Sequence< beans::PropertyValue > aArgs;
1112 TransformItems( SID_OPENDOC, rSet, aArgs );
1113 xModel->attachResource( GetMedium()->GetOrigURL(), aArgs );
1114 impl_addToModelCollection(xModel);
1117 pImpl->bModelInitialized = true;
1120 void SfxObjectShell::FinishedLoading( SfxLoadedFlags nFlags )
1122 bool bSetModifiedTRUE = false;
1123 const SfxStringItem* pSalvageItem = pMedium->GetItemSet().GetItem(SID_DOC_SALVAGE, false);
1124 if( ( nFlags & SfxLoadedFlags::MAINDOCUMENT ) && !(pImpl->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT )
1125 && !(pImpl->nFlagsInProgress & SfxLoadedFlags::MAINDOCUMENT ))
1127 pImpl->nFlagsInProgress |= SfxLoadedFlags::MAINDOCUMENT;
1128 static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes())->SetAttributes();
1130 if ( ( GetModifyPasswordHash() || GetModifyPasswordInfo().hasElements() ) && !IsModifyPasswordEntered() )
1131 SetReadOnly();
1133 // Salvage
1134 if ( pSalvageItem )
1135 bSetModifiedTRUE = true;
1137 if ( !IsEnableSetModified() )
1138 EnableSetModified();
1140 if( !bSetModifiedTRUE && IsEnableSetModified() )
1141 SetModified( false );
1143 CheckSecurityOnLoading_Impl();
1145 bHasName = true; // the document is loaded, so the name should already available
1146 GetTitle( SFX_TITLE_DETECT );
1147 InitOwnModel_Impl();
1149 if (IsLoadReadonly())
1151 OUString aFilterName;
1152 if (const SfxStringItem* pFilterNameItem =
1153 pMedium->GetItemSet().GetItem(SID_FILTER_NAME, false))
1154 aFilterName = pFilterNameItem->GetValue();
1156 OUString aFileName;
1157 if (const SfxStringItem* pFileNameItem =
1158 pMedium->GetItemSet().GetItem(SID_FILE_NAME, false))
1160 const INetURLObject aURL(pFileNameItem->GetValue());
1161 aFileName = aURL.getBase(INetURLObject::LAST_SEGMENT, true,
1162 INetURLObject::DecodeMechanism::WithCharset);
1165 bool bSilent = false;
1166 if (const SfxBoolItem* pSilentNameItem =
1167 pMedium->GetItemSet().GetItem(SID_SILENT, false))
1168 bSilent = pSilentNameItem->GetValue();
1170 if (!bSilent && aFilterName.indexOf("Excel") != -1)
1172 Reference<task::XInteractionHandler> xHandler(pMedium->GetInteractionHandler());
1173 if (xHandler.is())
1175 beans::NamedValue aLoadReadOnlyRequest;
1176 aLoadReadOnlyRequest.Name = "LoadReadOnlyRequest";
1177 aLoadReadOnlyRequest.Value <<= aFileName;
1179 Any aRequest(aLoadReadOnlyRequest);
1180 rtl::Reference<ucbhelper::SimpleInteractionRequest> xRequest
1181 = new ucbhelper::SimpleInteractionRequest(aRequest,
1182 ContinuationFlags::Approve |
1183 ContinuationFlags::Disapprove);
1185 xHandler->handle(xRequest);
1187 if (xRequest->getResponse() == ContinuationFlags::Disapprove)
1189 SetSecurityOptOpenReadOnly(false);
1190 pMedium->GetItemSet().Put(SfxBoolItem(SID_DOC_READONLY, false));
1196 pImpl->nFlagsInProgress &= ~SfxLoadedFlags::MAINDOCUMENT;
1199 if( ( nFlags & SfxLoadedFlags::IMAGES ) && !(pImpl->nLoadedFlags & SfxLoadedFlags::IMAGES )
1200 && !(pImpl->nFlagsInProgress & SfxLoadedFlags::IMAGES ))
1202 pImpl->nFlagsInProgress |= SfxLoadedFlags::IMAGES;
1203 uno::Reference<document::XDocumentProperties> xDocProps(
1204 getDocProperties());
1205 const OUString url(xDocProps->getAutoloadURL());
1206 sal_Int32 delay(xDocProps->getAutoloadSecs());
1207 SetAutoLoad( INetURLObject(url), delay * 1000,
1208 (delay > 0) || !url.isEmpty() );
1209 if( !bSetModifiedTRUE && IsEnableSetModified() )
1210 SetModified( false );
1211 Invalidate( SID_SAVEASDOC );
1212 pImpl->nFlagsInProgress &= ~SfxLoadedFlags::IMAGES;
1215 pImpl->nLoadedFlags |= nFlags;
1217 if ( pImpl->nFlagsInProgress != SfxLoadedFlags::NONE )
1218 return;
1220 // in case of reentrance calls the first called FinishedLoading() call on the stack
1221 // should do the notification, in result the notification is done when all the FinishedLoading() calls are finished
1223 if ( bSetModifiedTRUE )
1224 SetModified();
1225 else
1226 SetModified( false );
1228 if ( (pImpl->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) && (pImpl->nLoadedFlags & SfxLoadedFlags::IMAGES ) )
1230 const SfxBoolItem* pTemplateItem = pMedium->GetItemSet().GetItem(SID_TEMPLATE, false);
1231 bool bTemplate = pTemplateItem && pTemplateItem->GetValue();
1233 // closing the streams on loading should be under control of SFX!
1234 DBG_ASSERT( pMedium->IsOpen(), "Don't close the medium when loading documents!" );
1236 if ( bTemplate )
1238 TemplateDisconnectionAfterLoad();
1240 else
1242 // if a readonly medium has storage then it's stream is already based on temporary file
1243 if( !(pMedium->GetOpenMode() & StreamMode::WRITE) && !pMedium->HasStorage_Impl() )
1244 // don't lock file opened read only
1245 pMedium->CloseInStream();
1249 SetInitialized_Impl( false );
1251 // Title is not available until loading has finished
1252 Broadcast( SfxHint( SfxHintId::TitleChanged ) );
1253 if ( pImpl->nEventId != SfxEventHintId::NONE )
1254 PostActivateEvent_Impl(SfxViewFrame::GetFirst(this));
1257 void SfxObjectShell::TemplateDisconnectionAfterLoad()
1259 // document is created from a template
1260 //TODO/LATER: should the templates always be XML docs!
1262 SfxMedium* pTmpMedium = pMedium;
1263 if ( !pTmpMedium )
1264 return;
1266 const OUString aName( pTmpMedium->GetName() );
1267 const SfxStringItem* pTemplNamItem = pTmpMedium->GetItemSet().GetItem(SID_TEMPLATE_NAME, false);
1268 OUString aTemplateName;
1269 if ( pTemplNamItem )
1270 aTemplateName = pTemplNamItem->GetValue();
1271 else
1273 // !TODO/LATER: what's this?!
1274 // Interactive ( DClick, Contextmenu ) no long name is included
1275 aTemplateName = getDocProperties()->getTitle();
1276 if ( aTemplateName.isEmpty() )
1278 INetURLObject aURL( aName );
1279 aURL.CutExtension();
1280 aTemplateName = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
1284 // set medium to noname
1285 pTmpMedium->SetName( OUString(), true );
1286 pTmpMedium->Init_Impl();
1288 // drop resource
1289 SetNoName();
1290 InvalidateName();
1292 if( IsPackageStorageFormat_Impl( *pTmpMedium ) )
1294 // untitled document must be based on temporary storage
1295 // the medium should not dispose the storage in this case
1296 uno::Reference < embed::XStorage > xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
1297 GetStorage()->copyToStorage( xTmpStor );
1299 // the medium should disconnect from the original location
1300 // the storage should not be disposed since the document is still
1301 // based on it, but in DoSaveCompleted it will be disposed
1302 pTmpMedium->CanDisposeStorage_Impl( false );
1303 pTmpMedium->Close();
1305 // setting the new storage the medium will be based on
1306 pTmpMedium->SetStorage_Impl( xTmpStor );
1308 pMedium = nullptr;
1309 bool ok = DoSaveCompleted( pTmpMedium );
1310 assert(pMedium != nullptr);
1311 if( ok )
1313 const SfxStringItem* pSalvageItem = pMedium->GetItemSet().GetItem(SID_DOC_SALVAGE, false);
1314 bool bSalvage = pSalvageItem != nullptr;
1316 if ( !bSalvage )
1318 // some further initializations for templates
1319 SetTemplate_Impl( aName, aTemplateName, this );
1322 // the medium should not dispose the storage, DoSaveCompleted() has let it to do so
1323 pTmpMedium->CanDisposeStorage_Impl( false );
1325 else
1327 SetError(ERRCODE_IO_GENERAL);
1330 else
1332 // some further initializations for templates
1333 SetTemplate_Impl( aName, aTemplateName, this );
1334 pTmpMedium->CreateTempFile();
1337 // templates are never readonly
1338 pTmpMedium->GetItemSet().ClearItem( SID_DOC_READONLY );
1339 pTmpMedium->SetOpenMode( SFX_STREAM_READWRITE, true );
1341 // notifications about possible changes in readonly state and document info
1342 Broadcast( SfxHint(SfxHintId::ModeChanged) );
1344 // created untitled document can't be modified
1345 SetModified( false );
1349 bool SfxObjectShell::IsLoading() const
1350 /* [Description]
1352 Has FinishedLoading been called?
1355 return !( pImpl->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT );
1359 void SfxObjectShell::CancelTransfers()
1360 /* [Description]
1362 Here can Transfers get canceled, which were not registered
1363 by RegisterTransfer.
1366 if( ( pImpl->nLoadedFlags & SfxLoadedFlags::ALL ) != SfxLoadedFlags::ALL )
1368 pImpl->bIsAbortingImport = true;
1369 if( IsLoading() )
1370 FinishedLoading();
1375 AutoReloadTimer_Impl::AutoReloadTimer_Impl(
1376 OUString _aURL, sal_uInt32 nTime, SfxObjectShell* pSh )
1377 : Timer("sfx2 AutoReloadTimer_Impl"), aUrl(std::move( _aURL )), pObjSh( pSh )
1379 SetTimeout( nTime );
1383 void AutoReloadTimer_Impl::Invoke()
1385 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pObjSh );
1387 if ( pFrame )
1389 // Not possible/meaningful at the moment?
1390 if ( !pObjSh->CanReload_Impl() || pObjSh->IsAutoLoadLocked() || Application::IsUICaptured() )
1392 // Allow a retry
1393 Start();
1394 return;
1397 SfxAllItemSet aSet( SfxGetpApp()->GetPool() );
1398 aSet.Put( SfxBoolItem( SID_AUTOLOAD, true ) );
1399 if ( !aUrl.isEmpty() )
1400 aSet.Put( SfxStringItem( SID_FILE_NAME, aUrl ) );
1401 if (pObjSh->HasName()) {
1402 aSet.Put(
1403 SfxStringItem(SID_REFERER, pObjSh->GetMedium()->GetName()));
1405 SfxRequest aReq( SID_RELOAD, SfxCallMode::SLOT, aSet );
1406 // this will delete this
1407 pObjSh->Get_Impl()->pReloadTimer.reset();
1408 pFrame->ExecReload_Impl( aReq );
1409 return;
1412 // this will delete this
1413 pObjSh->Get_Impl()->pReloadTimer.reset();
1416 SfxModule* SfxObjectShell::GetModule() const
1418 return GetFactory().GetModule();
1421 ErrCode SfxObjectShell::CallBasic( std::u16string_view rMacro,
1422 std::u16string_view rBasic, SbxArray* pArgs,
1423 SbxValue* pRet )
1425 SfxApplication* pApp = SfxGetpApp();
1426 if( pApp->GetName() != rBasic )
1428 if ( !AdjustMacroMode() )
1429 return ERRCODE_IO_ACCESSDENIED;
1432 BasicManager *pMgr = GetBasicManager();
1433 if( pApp->GetName() == rBasic )
1434 pMgr = SfxApplication::GetBasicManager();
1435 ErrCode nRet = SfxApplication::CallBasic( OUString(rMacro), pMgr, pArgs, pRet );
1436 return nRet;
1439 bool SfxObjectShell::isScriptAccessAllowed( const Reference< XInterface >& _rxScriptContext )
1443 Reference< XEmbeddedScripts > xScripts( _rxScriptContext, UNO_QUERY );
1444 if ( !xScripts.is() )
1446 Reference< XScriptInvocationContext > xContext( _rxScriptContext, UNO_QUERY_THROW );
1447 xScripts.set( xContext->getScriptContainer(), UNO_SET_THROW );
1450 return xScripts->getAllowMacroExecution();
1452 catch( const Exception& )
1454 DBG_UNHANDLED_EXCEPTION("sfx.doc");
1456 return false;
1459 // don't allow LibreLogo to be used with our mouseover/etc dom-alike events
1460 bool SfxObjectShell::UnTrustedScript(const OUString& rScriptURL)
1462 if (!rScriptURL.startsWith("vnd.sun.star.script:"))
1463 return false;
1465 // ensure URL Escape Codes are decoded
1466 css::uno::Reference<css::uri::XUriReference> uri(
1467 css::uri::UriReferenceFactory::create(comphelper::getProcessComponentContext())->parse(rScriptURL));
1468 css::uno::Reference<css::uri::XVndSunStarScriptUrl> sfUri(uri, css::uno::UNO_QUERY);
1470 if (!sfUri.is())
1471 return false;
1473 // pyuno encodes path separator as |
1474 OUString sScript = sfUri->getName().replace('|', '/');
1476 // check if any path portion matches LibreLogo and ban it if it does
1477 sal_Int32 nIndex = 0;
1480 OUString aToken = sScript.getToken(0, '/', nIndex);
1481 if (aToken.startsWithIgnoreAsciiCase("LibreLogo") || aToken.indexOf('~') != -1)
1483 return true;
1486 while (nIndex >= 0);
1488 return false;
1491 ErrCode SfxObjectShell::CallXScript( const Reference< XInterface >& _rxScriptContext, const OUString& _rScriptURL,
1492 const Sequence< Any >& aParams, Any& aRet, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam, bool bRaiseError, const css::uno::Any* pCaller )
1494 SAL_INFO("sfx", "in CallXScript" );
1495 ErrCode nErr = ERRCODE_NONE;
1497 bool bCaughtException = false;
1498 Any aException;
1501 if (!isScriptAccessAllowed(_rxScriptContext))
1502 return ERRCODE_IO_ACCESSDENIED;
1504 if ( UnTrustedScript(_rScriptURL) )
1505 return ERRCODE_IO_ACCESSDENIED;
1507 // obtain/create a script provider
1508 Reference< provider::XScriptProvider > xScriptProvider;
1509 Reference< provider::XScriptProviderSupplier > xSPS( _rxScriptContext, UNO_QUERY );
1510 if ( xSPS.is() )
1511 xScriptProvider.set( xSPS->getScriptProvider() );
1513 if ( !xScriptProvider.is() )
1515 Reference< provider::XScriptProviderFactory > xScriptProviderFactory =
1516 provider::theMasterScriptProviderFactory::get( ::comphelper::getProcessComponentContext() );
1517 xScriptProvider.set( xScriptProviderFactory->createScriptProvider( Any( _rxScriptContext ) ), UNO_SET_THROW );
1520 // ry to protect the invocation context's undo manager (if present), just in case the script tampers with it
1521 ::framework::DocumentUndoGuard aUndoGuard( _rxScriptContext );
1523 // obtain the script, and execute it
1524 Reference< provider::XScript > xScript( xScriptProvider->getScript( _rScriptURL ), UNO_SET_THROW );
1525 if ( pCaller && pCaller->hasValue() )
1527 Reference< beans::XPropertySet > xProps( xScript, uno::UNO_QUERY );
1528 if ( xProps.is() )
1530 Sequence< uno::Any > aArgs{ *pCaller };
1531 xProps->setPropertyValue("Caller", uno::Any( aArgs ) );
1534 aRet = xScript->invoke( aParams, aOutParamIndex, aOutParam );
1536 catch ( const uno::Exception& )
1538 aException = ::cppu::getCaughtException();
1539 bCaughtException = true;
1540 nErr = ERRCODE_BASIC_INTERNAL_ERROR;
1543 if ( bCaughtException && bRaiseError )
1545 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1546 pFact->ShowAsyncScriptErrorDialog( nullptr, aException );
1549 SAL_INFO("sfx", "leaving CallXScript" );
1550 return nErr;
1553 // perhaps rename to CallScript once we get rid of the existing CallScript
1554 // and Call, CallBasic, CallStarBasic methods
1555 ErrCode SfxObjectShell::CallXScript( const OUString& rScriptURL,
1556 const css::uno::Sequence< css::uno::Any >& aParams,
1557 css::uno::Any& aRet,
1558 css::uno::Sequence< sal_Int16 >& aOutParamIndex,
1559 css::uno::Sequence< css::uno::Any >& aOutParam,
1560 bool bRaiseError,
1561 const css::uno::Any* pCaller )
1563 return CallXScript( GetModel(), rScriptURL, aParams, aRet, aOutParamIndex, aOutParam, bRaiseError, pCaller );
1566 void SfxHeaderAttributes_Impl::SetAttributes()
1568 bAlert = true;
1569 SvKeyValue aPair;
1570 for( bool bCont = xIter->GetFirst( aPair ); bCont;
1571 bCont = xIter->GetNext( aPair ) )
1572 SetAttribute( aPair );
1575 void SfxHeaderAttributes_Impl::SetAttribute( const SvKeyValue& rKV )
1577 const OUString& aValue = rKV.GetValue();
1578 if( rKV.GetKey().equalsIgnoreAsciiCase("refresh") && !rKV.GetValue().isEmpty() )
1580 sal_Int32 nIdx{ 0 };
1581 const sal_Int32 nTime{ o3tl::toInt32(o3tl::getToken(aValue, 0, ';', nIdx )) };
1582 const OUString aURL{ comphelper::string::strip(o3tl::getToken(aValue, 0, ';', nIdx ), ' ') };
1583 uno::Reference<document::XDocumentProperties> xDocProps(
1584 pDoc->getDocProperties());
1585 if( aURL.startsWithIgnoreAsciiCase( "url=" ) )
1587 try {
1588 xDocProps->setAutoloadURL(
1589 rtl::Uri::convertRelToAbs(pDoc->GetMedium()->GetName(), aURL.copy( 4 )) );
1590 } catch (rtl::MalformedUriException &) {
1591 TOOLS_WARN_EXCEPTION("sfx", "");
1596 xDocProps->setAutoloadSecs( nTime );
1598 catch (lang::IllegalArgumentException &)
1600 // ignore
1603 else if( rKV.GetKey().equalsIgnoreAsciiCase( "expires" ) )
1605 DateTime aDateTime( DateTime::EMPTY );
1606 if( INetMIMEMessage::ParseDateField( rKV.GetValue(), aDateTime ) )
1608 aDateTime.ConvertToLocalTime();
1609 pDoc->GetMedium()->SetExpired_Impl( aDateTime );
1611 else
1613 pDoc->GetMedium()->SetExpired_Impl( Date( 1, 1, 1970 ) );
1618 void SfxHeaderAttributes_Impl::Append( const SvKeyValue& rKV )
1620 xIter->Append( rKV );
1621 if( bAlert ) SetAttribute( rKV );
1624 SvKeyValueIterator* SfxObjectShell::GetHeaderAttributes()
1626 if( !pImpl->xHeaderAttributes.is() )
1628 DBG_ASSERT( pMedium, "No Medium" );
1629 pImpl->xHeaderAttributes = new SfxHeaderAttributes_Impl( this );
1631 return pImpl->xHeaderAttributes.get();
1634 void SfxObjectShell::ClearHeaderAttributesForSourceViewHack()
1636 static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes())
1637 ->ClearForSourceView();
1641 void SfxObjectShell::SetHeaderAttributesForSourceViewHack()
1643 static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes())
1644 ->SetAttributes();
1647 bool SfxObjectShell::IsPreview() const
1649 if ( !pMedium )
1650 return false;
1652 bool bPreview = false;
1653 const SfxStringItem* pFlags = pMedium->GetItemSet().GetItem(SID_OPTIONS, false);
1654 if ( pFlags )
1656 // Distributed values among individual items
1657 const OUString aFileFlags = pFlags->GetValue().toAsciiUpperCase();
1658 if ( -1 != aFileFlags.indexOf( 'B' ) )
1659 bPreview = true;
1662 if ( !bPreview )
1664 const SfxBoolItem* pItem = pMedium->GetItemSet().GetItem(SID_PREVIEW, false);
1665 if ( pItem )
1666 bPreview = pItem->GetValue();
1669 return bPreview;
1672 void SfxObjectShell::SetWaitCursor( bool bSet ) const
1674 for( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, this ) )
1676 if ( bSet )
1677 pFrame->GetFrame().GetWindow().EnterWait();
1678 else
1679 pFrame->GetFrame().GetWindow().LeaveWait();
1683 OUString SfxObjectShell::GetAPIName() const
1685 INetURLObject aURL( IsDocShared() ? GetSharedFileURL() : GetMedium()->GetName() );
1686 OUString aName( aURL.GetBase() );
1687 if( aName.isEmpty() )
1688 aName = aURL.GetURLNoPass();
1689 if ( aName.isEmpty() )
1690 aName = GetTitle( SFX_TITLE_DETECT );
1691 return aName;
1694 void SfxObjectShell::Invalidate( sal_uInt16 nId )
1696 for( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, this ) )
1697 Invalidate_Impl( pFrame->GetBindings(), nId );
1700 bool SfxObjectShell::AdjustMacroMode()
1702 uno::Reference< task::XInteractionHandler > xInteraction;
1703 if ( pMedium )
1704 xInteraction = pMedium->GetInteractionHandler();
1706 CheckForBrokenDocSignatures_Impl();
1708 CheckEncryption_Impl( xInteraction );
1710 return pImpl->aMacroMode.adjustMacroMode( xInteraction );
1713 css::uno::Reference<css::awt::XWindow> SfxObjectShell::GetDialogParent( SfxMedium const * pLoadingMedium )
1715 css::uno::Reference<css::awt::XWindow> xWindow;
1716 SfxItemSet& rSet = pLoadingMedium ? pLoadingMedium->GetItemSet() : GetMedium()->GetItemSet();
1717 const SfxUnoFrameItem* pUnoItem = rSet.GetItem(SID_FILLFRAME, false);
1718 if ( pUnoItem )
1720 const uno::Reference < frame::XFrame >& xFrame( pUnoItem->GetFrame() );
1721 xWindow = xFrame->getContainerWindow();
1724 if (!xWindow)
1726 SfxFrame* pFrame = nullptr;
1727 const SfxFrameItem* pFrameItem = rSet.GetItem<SfxFrameItem>(SID_DOCFRAME, false);
1728 if( pFrameItem && pFrameItem->GetFrame() )
1729 // get target frame from ItemSet
1730 pFrame = pFrameItem->GetFrame();
1731 else
1733 // try the current frame
1734 SfxViewFrame* pView = SfxViewFrame::Current();
1735 if ( !pView || pView->GetObjectShell() != this )
1736 // get any visible frame
1737 pView = SfxViewFrame::GetFirst(this);
1738 if ( pView )
1739 pFrame = &pView->GetFrame();
1742 if ( pFrame )
1744 // get topmost window
1745 xWindow = pFrame->GetFrameInterface()->getContainerWindow();
1749 if (xWindow)
1751 // this frame may be invisible, show it if it is allowed
1752 const SfxBoolItem* pHiddenItem = rSet.GetItem(SID_HIDDEN, false);
1753 if ( !pHiddenItem || !pHiddenItem->GetValue() )
1755 xWindow->setVisible(true);
1756 css::uno::Reference<css::awt::XTopWindow> xTopWindow(xWindow, uno::UNO_QUERY);
1757 SAL_WARN_IF(!xTopWindow, "sfx.appl", "XTopWindow not available from XWindow");
1758 if (xTopWindow)
1759 xTopWindow->toFront();
1763 return xWindow;
1766 void SfxObjectShell::SetCreateMode_Impl( SfxObjectCreateMode nMode )
1768 eCreateMode = nMode;
1771 bool SfxObjectShell::IsInPlaceActive() const
1773 if ( eCreateMode != SfxObjectCreateMode::EMBEDDED )
1774 return false;
1776 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
1777 return pFrame && pFrame->GetFrame().IsInPlace();
1780 bool SfxObjectShell::IsUIActive() const
1782 if ( eCreateMode != SfxObjectCreateMode::EMBEDDED )
1783 return false;
1785 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
1786 return pFrame && pFrame->GetFrame().IsInPlace() && pFrame->GetFrame().GetWorkWindow_Impl()->IsVisible_Impl();
1789 bool SfxObjectShell::UseInteractionToHandleError(
1790 const uno::Reference< task::XInteractionHandler >& xHandler,
1791 const ErrCodeMsg& nError )
1793 bool bResult = false;
1795 if ( xHandler.is() )
1799 uno::Any aInteraction;
1800 rtl::Reference<::comphelper::OInteractionAbort> pAbort = new ::comphelper::OInteractionAbort();
1801 rtl::Reference<::comphelper::OInteractionApprove> pApprove = new ::comphelper::OInteractionApprove();
1802 uno::Sequence< uno::Reference< task::XInteractionContinuation > > lContinuations{
1803 pAbort, pApprove
1806 task::ErrorCodeRequest2 aErrorCode(OUString(), uno::Reference<XInterface>(),
1807 sal_Int32(sal_uInt32(nError.GetCode())), nError.GetArg1(), nError.GetArg2(),
1808 static_cast<sal_Int16>(nError.GetDialogMask()));
1809 aInteraction <<= aErrorCode;
1810 xHandler->handle(::framework::InteractionRequest::CreateRequest (aInteraction,lContinuations));
1811 bResult = pAbort->wasSelected();
1813 catch( uno::Exception& )
1817 return bResult;
1820 sal_Int16 SfxObjectShell_Impl::getCurrentMacroExecMode() const
1822 sal_Int16 nImposedExecMode( MacroExecMode::NEVER_EXECUTE );
1824 const SfxMedium* pMedium( rDocShell.GetMedium() );
1825 OSL_PRECOND( pMedium, "SfxObjectShell_Impl::getCurrentMacroExecMode: no medium!" );
1826 if ( pMedium )
1828 const SfxUInt16Item* pMacroModeItem = pMedium->GetItemSet().GetItem(SID_MACROEXECMODE, false);
1829 if ( pMacroModeItem )
1830 nImposedExecMode = pMacroModeItem->GetValue();
1832 return nImposedExecMode;
1835 void SfxObjectShell_Impl::setCurrentMacroExecMode( sal_uInt16 nMacroMode )
1837 const SfxMedium* pMedium( rDocShell.GetMedium() );
1838 OSL_PRECOND( pMedium, "SfxObjectShell_Impl::getCurrentMacroExecMode: no medium!" );
1839 if ( pMedium )
1841 pMedium->GetItemSet().Put( SfxUInt16Item( SID_MACROEXECMODE, nMacroMode ) );
1845 OUString SfxObjectShell_Impl::getDocumentLocation() const
1847 OUString sLocation;
1849 const SfxMedium* pMedium( rDocShell.GetMedium() );
1850 OSL_PRECOND( pMedium, "SfxObjectShell_Impl::getDocumentLocation: no medium!" );
1851 if ( pMedium )
1853 sLocation = pMedium->GetName();
1854 if ( sLocation.isEmpty() )
1856 // for documents made from a template: get the name of the template
1857 sLocation = rDocShell.getDocProperties()->getTemplateURL();
1860 // tdf#128006 take document base url as location
1861 if (sLocation.isEmpty())
1862 sLocation = rDocShell.getDocumentBaseURL();
1865 return sLocation;
1868 bool SfxObjectShell_Impl::documentStorageHasMacros() const
1870 return ::sfx2::DocumentMacroMode::storageHasMacros( m_xDocStorage );
1873 bool SfxObjectShell_Impl::macroCallsSeenWhileLoading() const
1875 return rDocShell.GetMacroCallsSeenWhileLoading();
1878 Reference< XEmbeddedScripts > SfxObjectShell_Impl::getEmbeddedDocumentScripts() const
1880 return Reference< XEmbeddedScripts >( rDocShell.GetModel(), UNO_QUERY );
1883 SignatureState SfxObjectShell_Impl::getScriptingSignatureState()
1885 SignatureState nSignatureState( rDocShell.GetScriptingSignatureState() );
1887 if ( nSignatureState != SignatureState::NOSIGNATURES && m_bMacroSignBroken )
1889 // if there is a macro signature it must be handled as broken
1890 nSignatureState = SignatureState::BROKEN;
1893 return nSignatureState;
1896 bool SfxObjectShell_Impl::hasTrustedScriptingSignature(
1897 const css::uno::Reference<css::task::XInteractionHandler>& _rxInteraction)
1899 bool bResult = false;
1903 if ( nScriptingSignatureState == SignatureState::UNKNOWN
1904 || nScriptingSignatureState == SignatureState::OK
1905 || nScriptingSignatureState == SignatureState::NOTVALIDATED )
1907 OUString aVersion;
1910 uno::Reference < beans::XPropertySet > xPropSet( rDocShell.GetStorage(), uno::UNO_QUERY_THROW );
1911 xPropSet->getPropertyValue("Version") >>= aVersion;
1913 catch( uno::Exception& )
1917 uno::Reference< security::XDocumentDigitalSignatures > xSigner( security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), aVersion) );
1919 const uno::Sequence< security::DocumentSignatureInformation > aInfo = rDocShell.GetDocumentSignatureInformation( true, xSigner );
1921 if ( aInfo.hasElements() )
1923 if ( nScriptingSignatureState == SignatureState::UNKNOWN )
1924 nScriptingSignatureState = DocumentSignatures::getSignatureState(aInfo);
1926 if ( nScriptingSignatureState == SignatureState::OK
1927 || nScriptingSignatureState == SignatureState::NOTVALIDATED )
1929 bResult = std::any_of(aInfo.begin(), aInfo.end(),
1930 [&xSigner](const security::DocumentSignatureInformation& rInfo) {
1931 return xSigner->isAuthorTrusted( rInfo.Signer ); });
1933 if (!bResult && _rxInteraction)
1935 task::DocumentMacroConfirmationRequest aRequest;
1936 aRequest.DocumentURL = getDocumentLocation();
1937 aRequest.DocumentStorage = rDocShell.GetMedium()->GetScriptingStorageToSign_Impl();
1938 aRequest.DocumentSignatureInformation = aInfo;
1939 aRequest.DocumentVersion = aVersion;
1940 aRequest.Classification = task::InteractionClassification_QUERY;
1941 bResult = SfxMedium::CallApproveHandler( _rxInteraction, uno::Any( aRequest ), true );
1947 catch( uno::Exception& )
1950 return bResult;
1953 bool SfxObjectShell::IsContinueImportOnFilterExceptions()
1955 if (mbContinueImportOnFilterExceptions == undefined)
1957 if (!pMedium)
1959 mbContinueImportOnFilterExceptions = no;
1960 return false;
1963 if (utl::MediaDescriptor desc(pMedium->GetArgs());
1964 !desc.getUnpackedValueOrDefault("RepairAllowed", true))
1966 mbContinueImportOnFilterExceptions = no;
1967 return false;
1970 if (const SfxBoolItem* pRepairItem
1971 = pMedium->GetItemSet().GetItem(SID_REPAIRPACKAGE, false);
1972 pRepairItem && pRepairItem->GetValue())
1974 mbContinueImportOnFilterExceptions = yes;
1975 return true;
1978 auto xInteractionHandler = pMedium->GetInteractionHandler();
1979 if (!xInteractionHandler)
1981 mbContinueImportOnFilterExceptions = no;
1982 return false;
1985 const OUString aDocName(pMedium->GetURLObject().getName(
1986 INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset));
1987 RequestPackageReparation aRequest(aDocName);
1988 xInteractionHandler->handle(aRequest.GetRequest());
1989 if (aRequest.isApproved())
1991 mbContinueImportOnFilterExceptions = yes;
1992 // lok: we want to overwrite file in jail, so don't use template flag
1993 bool bIsLOK = comphelper::LibreOfficeKit::isActive();
1994 // allow repair
1995 pMedium->GetItemSet().Put(SfxBoolItem(SID_REPAIRPACKAGE, true));
1996 pMedium->GetItemSet().Put(SfxBoolItem(SID_TEMPLATE, !bIsLOK));
1997 pMedium->GetItemSet().Put(SfxStringItem(SID_DOCINFO_TITLE, aDocName));
1999 else
2000 mbContinueImportOnFilterExceptions = no;
2002 return mbContinueImportOnFilterExceptions == yes;
2005 bool SfxObjectShell::isEditDocLocked() const
2007 Reference<XModel3> xModel = GetModel();
2008 if (!xModel.is())
2009 return false;
2010 if (!officecfg::Office::Common::Misc::AllowEditReadonlyDocs::get())
2011 return true;
2012 return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockEditDoc" } ), u"LockEditDoc", false);
2015 bool SfxObjectShell::isContentExtractionLocked() const
2017 Reference<XModel3> xModel = GetModel();
2018 if (!xModel.is())
2019 return false;
2020 return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockContentExtraction" } ), u"LockContentExtraction", false);
2023 bool SfxObjectShell::isExportLocked() const
2025 Reference<XModel3> xModel = GetModel();
2026 if (!xModel.is())
2027 return false;
2028 return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockExport" } ), u"LockExport", false);
2031 bool SfxObjectShell::isPrintLocked() const
2033 Reference<XModel3> xModel = GetModel();
2034 if (!xModel.is())
2035 return false;
2036 return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockPrint" } ), u"LockPrint", false);
2039 bool SfxObjectShell::isSaveLocked() const
2041 Reference<XModel3> xModel = GetModel();
2042 if (!xModel.is())
2043 return false;
2044 return comphelper::NamedValueCollection::getOrDefault(xModel->getArgs2( { "LockSave" } ), u"LockSave", false);
2047 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */