/* -*- 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 .
*/
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;
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
{ // tdf#146547 read-only does not prevent modified, instead try to prevent // setting "internal" documents that may be displayed in some dialog but // which the user didn't load or activate to modified. return pImpl->m_bEnableSetModified && !IsPreview()
&& eCreateMode != SfxObjectCreateMode::ORGANIZER
&& eCreateMode != SfxObjectCreateMode::INTERNAL // tdf#157931 form documents only in design mode
&& ((pImpl->pBaseModel
&& !pImpl->pBaseModel->impl_isDisposed()
&& pImpl->pBaseModel->IsInitialized()
&& pImpl->pBaseModel->getIdentifier() != "com.sun.star.sdb.FormDesign")
|| !IsReadOnly());
}
bool SfxObjectShell::IsModified() const
{ if ( pImpl->m_bIsModified ) returntrue;
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
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 ) );
// Don't wait to get this important state via binding notification timeout. if ( comphelper::LibreOfficeKit::isActive() )
{
OString aStatus = ".uno:ModifiedStatus="_ostr;
aStatus += IsModified() ? "true" : "false";
SfxLokHelper::notifyAllViews(LOK_CALLBACK_STATE_CHANGED, aStatus);
}
}
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()>.
*/
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();
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;
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 SfxPoolItemHolder aItem(pViewFrame->GetBindings().ExecuteSynchron( HasName() ? SID_SAVEDOC : SID_SAVEASDOC )); const SfxBoolItem* pResult(dynamic_cast<const SfxBoolItem*>(aItem.getItem()));
bResult = ( pResult && pResult->GetValue() ); if ( bResult )
aOrigURL = GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE );
}
}
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
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.
*/
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.
*/
if ( pMed )
{ const SfxStringItem* pNameItem = pMed->GetItemSet().GetItem(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 = pMed->GetItemSet().GetItem(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);
// 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.
*/
void SfxObjectShell::CheckSecurityOnLoading_Impl()
{ if (GetErrorCode() == ERRCODE_IO_BROKENPACKAGE)
{ // safety first: don't run any macros from broken package.
pImpl->aMacroMode.disallowMacroExecution(); return; // do not get signature status - needs to be done after RepairPackage
}
// make sure LO evaluates the macro signatures, so it can be preserved
GetScriptingSignatureState();
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);
if (!bSilent && aFilterName.indexOf("Excel") != -1)
{
Reference<task::XInteractionHandler> xHandler(pMedium->GetInteractionHandler()); if (xHandler.is())
{
beans::NamedValue aLoadReadOnlyRequest;
aLoadReadOnlyRequest.Name = "LoadReadOnlyRequest";
aLoadReadOnlyRequest.Value <<= aFileName;
Any aRequest(aLoadReadOnlyRequest);
rtl::Reference<ucbhelper::SimpleInteractionRequest> xRequest
= new ucbhelper::SimpleInteractionRequest(aRequest,
ContinuationFlags::Approve |
ContinuationFlags::Disapprove);
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 );
// 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 = pTmpMedium->GetItemSet().GetItem(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 );
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 );
}
Here can Transfers get canceled, which were not registered by RegisterTransfer.
*/
{ if( ( pImpl->nLoadedFlags & SfxLoadedFlags::ALL ) != SfxLoadedFlags::ALL )
{
pImpl->bIsAbortingImport = true; if( IsLoading() )
FinishedLoading();
}
}
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();
}
// 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:")) returnfalse;
// 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)
{ returntrue;
}
} while (nIndex >= 0);
// ry to protect the invocation context's undo manager (if present), just in case the script tampers with it
::framework::DocumentUndoGuard aUndoGuard( _rxScriptContext );
if (!xWindow)
{
SfxFrame* pFrame = nullptr; const SfxFrameItem* pFrameItem = rSet.GetItem<SfxFrameItem>(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 = rSet.GetItem(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();
}
}
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();
}
if ( nSignatureState != SignatureState::NOSIGNATURES && m_bMacroSignBroken )
{ // if there is a macro signature it must be handled as broken
nSignatureState = SignatureState::BROKEN;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.