diff options
-rwxr-xr-x | framework/inc/helper/documentundoguard.hxx | 68 | ||||
-rw-r--r-- | framework/prj/d.lst | 1 | ||||
-rwxr-xr-x | framework/source/helper/documentundoguard.cxx | 272 | ||||
-rw-r--r-- | framework/source/helper/makefile.mk | 3 | ||||
-rw-r--r-- | framework/util/makefile.mk | 3 | ||||
-rw-r--r-- | scripting/source/protocolhandler/makefile.mk | 1 | ||||
-rw-r--r-- | scripting/source/protocolhandler/scripthandler.cxx | 6 | ||||
-rw-r--r-- | sfx2/source/appl/appuno.cxx | 62 | ||||
-rw-r--r-- | sfx2/source/doc/objmisc.cxx | 5 |
9 files changed, 395 insertions, 26 deletions
diff --git a/framework/inc/helper/documentundoguard.hxx b/framework/inc/helper/documentundoguard.hxx new file mode 100755 index 000000000000..d5856341e30e --- /dev/null +++ b/framework/inc/helper/documentundoguard.hxx @@ -0,0 +1,68 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef FRAMEWORK_DOCUMENTUNDOGUARD_HXX +#define FRAMEWORK_DOCUMENTUNDOGUARD_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/uno/XInterface.hpp> +/** === end UNO includes === **/ + +#include <boost/scoped_ptr.hpp> + +//...................................................................................................................... +namespace framework +{ +//...................................................................................................................... + + //================================================================================================================== + //= DocumentUndoGuard + //================================================================================================================== + struct DocumentUndoGuard_Data; + /** a helper class guarding the Undo manager of a document + + This class guards, within a given scope, the Undo Manager of a document (or another component supporting + the XUndoManagerSupplier interface). When entering the scope (i.e. when the <code>DocumentUndoGuard</code> + instances is constructed), the current state of the undo contexts of the undo manager is examined. + Upon leaving the scope (i.e. when the <code>DocumentUndoGuard</code> is destructed), the guard will execute + as many calls to <member scope="com::sun::star::document">XUndoManager::leaveUndoContext</member> as are + necessary to restore the manager's initial state. + */ + class DocumentUndoGuard + { + public: + DocumentUndoGuard( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& i_undoSupplierComponent ); + ~DocumentUndoGuard(); + + private: + ::boost::scoped_ptr< DocumentUndoGuard_Data > m_pData; + }; + +//...................................................................................................................... +} // namespace framework +//...................................................................................................................... + +#endif // FRAMEWORK_DOCUMENTUNDOGUARD_HXX diff --git a/framework/prj/d.lst b/framework/prj/d.lst index d3a3d6dd153c..d9d030d95b5e 100644 --- a/framework/prj/d.lst +++ b/framework/prj/d.lst @@ -43,6 +43,7 @@ mkdir: %_DEST%\xml%_EXT%\uiconfig\modules\StartModule\statusbar ..\inc\interaction\preventduplicateinteraction.hxx %_DEST%\inc%_EXT%\framework\preventduplicateinteraction.hxx ..\inc\helper\titlehelper.hxx %_DEST%\inc%_EXT%\framework\titlehelper.hxx ..\inc\classes\framelistanalyzer.hxx %_DEST%\inc%_EXT%\framework\framelistanalyzer.hxx +..\inc\helper\documentundoguard.hxx %_DEST%\inc%_EXT%\framework\documentundoguard.hxx ..\uiconfig\startmodule\menubar\*.xml %_DEST%\xml%_EXT%\uiconfig\modules\StartModule\menubar\*.xml ..\uiconfig\startmodule\toolbar\*.xml %_DEST%\xml%_EXT%\uiconfig\modules\StartModule\toolbar\*.xml diff --git a/framework/source/helper/documentundoguard.cxx b/framework/source/helper/documentundoguard.cxx new file mode 100755 index 000000000000..03e2fae5f6a6 --- /dev/null +++ b/framework/source/helper/documentundoguard.cxx @@ -0,0 +1,272 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_framework.hxx" + +#include <helper/documentundoguard.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/document/XUndoManagerSupplier.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> + +//...................................................................................................................... +namespace framework +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::document::XUndoManagerSupplier; + using ::com::sun::star::document::XUndoManager; + using ::com::sun::star::document::XUndoManagerListener; + using ::com::sun::star::document::UndoManagerEvent; + using ::com::sun::star::lang::EventObject; + /** === end UNO using === **/ + + //================================================================================================================== + //= UndoManagerContextListener + //================================================================================================================== + typedef ::cppu::WeakImplHelper1 < XUndoManagerListener + > UndoManagerContextListener_Base; + class UndoManagerContextListener : public UndoManagerContextListener_Base + { + public: + UndoManagerContextListener( const Reference< XUndoManager >& i_undoManager ) + :m_xUndoManager( i_undoManager, UNO_SET_THROW ) + ,m_nRelativeContextDepth( 0 ) + ,m_documentDisposed( false ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + m_xUndoManager->addUndoManagerListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + UndoManagerContextListener() + { + } + + void finish() + { + OSL_ENSURE( m_nRelativeContextDepth >= 0, "UndoManagerContextListener: more contexts left than entered?" ); + + if ( m_documentDisposed ) + return; + + // work with a copy of m_nRelativeContextDepth, to be independent from possible bugs in the + // listener notifications (where it would be decremented with every leaveUndoContext) + sal_Int32 nDepth = m_nRelativeContextDepth; + while ( nDepth-- > 0 ) + { + m_xUndoManager->leaveUndoContext(); + } + m_xUndoManager->removeUndoManagerListener( this ); + } + + // XUndoManagerListener + virtual void SAL_CALL undoActionAdded( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL actionUndone( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL actionRedone( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL allActionsCleared( const EventObject& i_event ) throw (RuntimeException); + virtual void SAL_CALL redoActionsCleared( const EventObject& i_event ) throw (RuntimeException); + virtual void SAL_CALL resetAll( const EventObject& i_event ) throw (RuntimeException); + virtual void SAL_CALL enteredContext( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL enteredHiddenContext( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL leftContext( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL leftHiddenContext( const UndoManagerEvent& i_event ) throw (RuntimeException); + virtual void SAL_CALL cancelledContext( const UndoManagerEvent& i_event ) throw (RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const EventObject& i_event ) throw (RuntimeException); + + private: + Reference< XUndoManager > const m_xUndoManager; + oslInterlockedCount m_nRelativeContextDepth; + bool m_documentDisposed; + }; + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::undoActionAdded( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + // not interested in + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::actionUndone( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + // not interested in + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::actionRedone( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + // not interested in + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::allActionsCleared( const EventObject& i_event ) throw (RuntimeException) + { + (void)i_event; + // not interested in + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::redoActionsCleared( const EventObject& i_event ) throw (RuntimeException) + { + (void)i_event; + // not interested in + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::resetAll( const EventObject& i_event ) throw (RuntimeException) + { + (void)i_event; + m_nRelativeContextDepth = 0; + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::enteredContext( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + osl_incrementInterlockedCount( &m_nRelativeContextDepth ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::enteredHiddenContext( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + osl_incrementInterlockedCount( &m_nRelativeContextDepth ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::leftContext( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + osl_decrementInterlockedCount( &m_nRelativeContextDepth ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::leftHiddenContext( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + osl_decrementInterlockedCount( &m_nRelativeContextDepth ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::cancelledContext( const UndoManagerEvent& i_event ) throw (RuntimeException) + { + (void)i_event; + osl_decrementInterlockedCount( &m_nRelativeContextDepth ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL UndoManagerContextListener::disposing( const EventObject& i_event ) throw (RuntimeException) + { + (void)i_event; + m_documentDisposed = true; + } + + //================================================================================================================== + //= DocumentUndoGuard_Data + //================================================================================================================== + struct DocumentUndoGuard_Data + { + Reference< XUndoManager > xUndoManager; + ::rtl::Reference< UndoManagerContextListener > pContextListener; + }; + + namespace + { + //-------------------------------------------------------------------------------------------------------------- + void lcl_init( DocumentUndoGuard_Data& i_data, const Reference< XInterface >& i_undoSupplierComponent ) + { + try + { + Reference< XUndoManagerSupplier > xUndoSupplier( i_undoSupplierComponent, UNO_QUERY ); + if ( xUndoSupplier.is() ) + i_data.xUndoManager.set( xUndoSupplier->getUndoManager(), UNO_SET_THROW ); + + if ( i_data.xUndoManager.is() ) + i_data.pContextListener.set( new UndoManagerContextListener( i_data.xUndoManager ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------------------------------------------------- + void lcl_restore( DocumentUndoGuard_Data& i_data ) + { + try + { + if ( i_data.pContextListener.is() ) + i_data.pContextListener->finish(); + i_data.pContextListener.clear(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + + //================================================================================================================== + //= DocumentUndoGuard + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + DocumentUndoGuard::DocumentUndoGuard( const Reference< XInterface >& i_undoSupplierComponent ) + :m_pData( new DocumentUndoGuard_Data ) + { + lcl_init( *m_pData, i_undoSupplierComponent ); + } + + DocumentUndoGuard::~DocumentUndoGuard() + { + lcl_restore( *m_pData ); + } + +//...................................................................................................................... +} // namespace framework +//...................................................................................................................... diff --git a/framework/source/helper/makefile.mk b/framework/source/helper/makefile.mk index ed54c381160c..158fba424c51 100644 --- a/framework/source/helper/makefile.mk +++ b/framework/source/helper/makefile.mk @@ -62,7 +62,8 @@ SLOFILES= $(SLO)$/ocomponentaccess.obj \ $(SLO)$/tagwindowasmodified.obj \ $(SLO)$/titlebarupdate.obj \ $(SLO)$/titlehelper.obj \ - $(SLO)$/mischelper.obj + $(SLO)$/mischelper.obj \ + $(SLO)$/documentundoguard.obj \ # --- Targets ------------------------------------------------------ diff --git a/framework/util/makefile.mk b/framework/util/makefile.mk index a3f14341d3f3..3df1e6493c9f 100644 --- a/framework/util/makefile.mk +++ b/framework/util/makefile.mk @@ -99,7 +99,8 @@ LIB2OBJFILES= \ $(SLO)$/menuextensionsupplier.obj \ $(SLO)$/preventduplicateinteraction.obj \ $(SLO)$/framelistanalyzer.obj \ - $(SLO)$/titlehelper.obj + $(SLO)$/titlehelper.obj \ + $(SLO)$/documentundoguard.obj \ # --- import classes library --------------------------------------------------- diff --git a/scripting/source/protocolhandler/makefile.mk b/scripting/source/protocolhandler/makefile.mk index ec69c00b209d..5a2e92bbbac3 100644 --- a/scripting/source/protocolhandler/makefile.mk +++ b/scripting/source/protocolhandler/makefile.mk @@ -45,6 +45,7 @@ SHL1TARGET= $(TARGET)$(DLLPOSTFIX) SHL1STDLIBS= \ $(SFXLIB) \ + $(FWELIB) \ $(CPPULIB) \ $(CPPUHELPERLIB) \ $(VCLLIB) \ diff --git a/scripting/source/protocolhandler/scripthandler.cxx b/scripting/source/protocolhandler/scripthandler.cxx index 4e81426d7d53..7c24b98e5a71 100644 --- a/scripting/source/protocolhandler/scripthandler.cxx +++ b/scripting/source/protocolhandler/scripthandler.cxx @@ -53,6 +53,7 @@ #include <cppuhelper/factory.hxx> #include <cppuhelper/exc_hlp.hxx> #include <util/util.hxx> +#include <framework/documentundoguard.hxx> #include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uri/XUriReference.hpp" @@ -207,6 +208,11 @@ void SAL_CALL ScriptProtocolHandler::dispatchWithNotification( } } + // attempt to protect the document against the script tampering with its Undo Context + ::std::auto_ptr< ::framework::DocumentUndoGuard > pUndoGuard; + if ( bIsDocumentScript ) + pUndoGuard.reset( new ::framework::DocumentUndoGuard( m_xScriptInvocation ) ); + bSuccess = sal_False; while ( !bSuccess ) { diff --git a/sfx2/source/appl/appuno.cxx b/sfx2/source/appl/appuno.cxx index 239b5bd58d9b..eebc5a930c03 100644 --- a/sfx2/source/appl/appuno.cxx +++ b/sfx2/source/appl/appuno.cxx @@ -96,6 +96,7 @@ #include <tools/cachestr.hxx> #include <osl/mutex.hxx> #include <comphelper/sequence.hxx> +#include <framework/documentundoguard.hxx> #include <rtl/ustrbuf.hxx> using namespace ::com::sun::star; @@ -1771,18 +1772,21 @@ ErrCode SfxMacroLoader::loadMacro( const ::rtl::OUString& rURL, com::sun::star:: if ( pBasMgr ) { - if ( pSh && pDoc ) + const bool bIsAppBasic = ( pBasMgr == pAppMgr ); + const bool bIsDocBasic = ( pBasMgr != pAppMgr ); + + if ( pDoc ) { - // security check for macros from document basic if an SFX context (pSh) is given + // security check for macros from document basic if an SFX doc is given if ( !pDoc->AdjustMacroMode( String() ) ) // check forbids execution return ERRCODE_IO_ACCESSDENIED; } - else if ( pSh && pSh->GetMedium() ) + else if ( pDoc && pDoc->GetMedium() ) { - pSh->AdjustMacroMode( String() ); - SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False); - SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pMacroExecModeItem, SfxUInt16Item, SID_MACROEXECMODE, sal_False); + pDoc->AdjustMacroMode( String() ); + SFX_ITEMSET_ARG( pDoc->GetMedium()->GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False); + SFX_ITEMSET_ARG( pDoc->GetMedium()->GetItemSet(), pMacroExecModeItem, SfxUInt16Item, SID_MACROEXECMODE, sal_False); if ( pUpdateDocItem && pMacroExecModeItem && pUpdateDocItem->GetValue() == document::UpdateDocMode::NO_UPDATE && pMacroExecModeItem->GetValue() == document::MacroExecMode::NEVER_EXECUTE ) @@ -1802,34 +1806,46 @@ ErrCode SfxMacroLoader::loadMacro( const ::rtl::OUString& rURL, com::sun::star:: if ( pBasMgr->HasMacro( aQualifiedMethod ) ) { Any aOldThisComponent; - if ( pSh ) + const bool bSetDocMacroMode = ( pDoc != NULL ) && bIsDocBasic; + const bool bSetGlobalThisComponent = ( pDoc != NULL ) && bIsAppBasic; + if ( bSetDocMacroMode ) { - if ( pBasMgr != pAppMgr ) - // mark document: it executes an own macro, so it's in a modal mode - pSh->SetMacroMode_Impl( TRUE ); - if ( pBasMgr == pAppMgr ) - { - // document is executed via AppBASIC, adjust ThisComponent variable - aOldThisComponent = pAppMgr->SetGlobalUNOConstant( "ThisComponent", makeAny( pSh->GetModel() ) ); - } + // mark document: it executes an own macro, so it's in a modal mode + pDoc->SetMacroMode_Impl( TRUE ); + } + + if ( bSetGlobalThisComponent ) + { + // document is executed via AppBASIC, adjust ThisComponent variable + aOldThisComponent = pAppMgr->SetGlobalUNOConstant( "ThisComponent", makeAny( pDoc->GetModel() ) ); } // just to let the shell be alive - SfxObjectShellRef rSh = pSh; + SfxObjectShellRef xKeepDocAlive = pDoc; - SbxVariableRef retValRef = new SbxVariable; - nErr = pBasMgr->ExecuteMacro( aQualifiedMethod, aArgs, retValRef ); - if ( nErr == ERRCODE_NONE ) - rRetval = sbxToUnoValue( retValRef ); + { + // attempt to protect the document against the script tampering with its Undo Context + ::std::auto_ptr< ::framework::DocumentUndoGuard > pUndoGuard; + if ( bIsDocBasic ) + pUndoGuard.reset( new ::framework::DocumentUndoGuard( pDoc->GetModel() ) ); + + // execute the method + SbxVariableRef retValRef = new SbxVariable; + nErr = pBasMgr->ExecuteMacro( aQualifiedMethod, aArgs, retValRef ); + if ( nErr == ERRCODE_NONE ) + rRetval = sbxToUnoValue( retValRef ); + } - if ( ( pBasMgr == pAppMgr ) && pSh ) + if ( bSetGlobalThisComponent ) { pAppMgr->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); } - if ( pSh && pSh->GetModel().is() ) + if ( bSetDocMacroMode ) + { // remove flag for modal mode - pSh->SetMacroMode_Impl( FALSE ); + pDoc->SetMacroMode_Impl( FALSE ); + } } else nErr = ERRCODE_BASIC_PROC_UNDEFINED; diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx index 0c4d4b64b204..7278baf816ee 100644 --- a/sfx2/source/doc/objmisc.cxx +++ b/sfx2/source/doc/objmisc.cxx @@ -118,6 +118,7 @@ using namespace ::com::sun::star::container; #include <rtl/bootstrap.hxx> #include <vcl/svapp.hxx> #include <framework/interaction.hxx> +#include <framework/documentundoguard.hxx> #include <comphelper/storagehelper.hxx> #include <comphelper/documentconstants.hxx> @@ -1721,9 +1722,11 @@ ErrCode SfxObjectShell::CallXScript( const Reference< XInterface >& _rxScriptCon xScriptProvider.set( xScriptProviderFactory->createScriptProvider( makeAny( _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.get() ); + // obtain the script, and execute it Reference< provider::XScript > xScript( xScriptProvider->getScript( _rScriptURL ), UNO_QUERY_THROW ); - aRet = xScript->invoke( aParams, aOutParamIndex, aOutParam ); } catch ( const uno::Exception& ) |