diff options
-rw-r--r-- | include/sfx2/appuno.hxx | 35 | ||||
-rw-r--r-- | sfx2/Library_sfx.mk | 1 | ||||
-rw-r--r-- | sfx2/source/appl/appuno.cxx | 277 | ||||
-rw-r--r-- | sfx2/source/appl/macroloader.cxx | 349 | ||||
-rw-r--r-- | sfx2/source/inc/macroloader.hxx | 94 | ||||
-rw-r--r-- | sfx2/source/notify/eventsupplier.cxx | 2 | ||||
-rw-r--r-- | sfx2/util/sfx.component | 3 |
7 files changed, 447 insertions, 314 deletions
diff --git a/include/sfx2/appuno.hxx b/include/sfx2/appuno.hxx index a513dbc7505c..a022328f13f0 100644 --- a/include/sfx2/appuno.hxx +++ b/include/sfx2/appuno.hxx @@ -46,41 +46,6 @@ #include <tools/errcode.hxx> #include <sfx2/sfxuno.hxx> -class SfxObjectShell; -class SfxMacroLoader : public ::cppu::WeakImplHelper5< - css::frame::XDispatchProvider, - css::frame::XNotifyingDispatch, - css::frame::XSynchronousDispatch, - css::lang::XServiceInfo, - css::lang::XInitialization > -{ - ::com::sun::star::uno::WeakReference < ::com::sun::star::frame::XFrame > m_xFrame; - - SfxObjectShell* GetObjectShell_Impl(); - -public: - // XInterface, XTypeProvider, XServiceInfo - SFX_DECL_XSERVICEINFO - - SfxMacroLoader( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ) - {} - - static ErrCode loadMacro( const OUString& aURL, ::com::sun::star::uno::Any& rRetval, SfxObjectShell* pDoc=NULL ) throw( ::com::sun::star::uno::RuntimeException ); - - virtual ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > SAL_CALL - queryDispatch( const ::com::sun::star::util::URL& aURL, const OUString& sTargetFrameName, - FrameSearchFlags eSearchFlags ) throw( ::com::sun::star::uno::RuntimeException ) ; - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > > SAL_CALL - queryDispatches( const ::com::sun::star::uno::Sequence < ::com::sun::star::frame::DispatchDescriptor >& seqDescriptor ) - throw( ::com::sun::star::uno::RuntimeException ) ; - virtual void SAL_CALL dispatchWithNotification( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArgs, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchResultListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArgs ) throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Any SAL_CALL dispatchWithReturnValue( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArgs ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL addStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& xControl, const ::com::sun::star::util::URL& aURL ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& xControl, const ::com::sun::star::util::URL& aURL ) throw (::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); -}; - class SfxAppDispatchProvider : public ::cppu::WeakImplHelper3< ::com::sun::star::frame::XAppDispatchProvider, ::com::sun::star::lang::XServiceInfo, ::com::sun::star::lang::XInitialization > diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk index b6e0962bbf9f..f6e39b37cec2 100644 --- a/sfx2/Library_sfx.mk +++ b/sfx2/Library_sfx.mk @@ -107,6 +107,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\ sfx2/source/appl/linkmgr2 \ sfx2/source/appl/linksrc \ sfx2/source/appl/lnkbase2 \ + sfx2/source/appl/macroloader \ sfx2/source/appl/module \ sfx2/source/appl/newhelp \ sfx2/source/appl/opengrf \ diff --git a/sfx2/source/appl/appuno.cxx b/sfx2/source/appl/appuno.cxx index 50f8ee613697..109cc2d7028f 100644 --- a/sfx2/source/appl/appuno.cxx +++ b/sfx2/source/appl/appuno.cxx @@ -115,8 +115,6 @@ #include <boost/scoped_ptr.hpp> -#define PROTOCOLHANDLER_SERVICENAME "com.sun.star.frame.ProtocolHandler" - using namespace ::com::sun::star; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::uno; @@ -1707,280 +1705,6 @@ void TransformItems( sal_uInt16 nSlotId, const SfxItemSet& rSet, uno::Sequence<b rArgs = aSequ; } -SFX_IMPL_XSERVICEINFO( SfxMacroLoader, PROTOCOLHANDLER_SERVICENAME, "com.sun.star.comp.sfx2.SfxMacroLoader" ) -SFX_IMPL_SINGLEFACTORY( SfxMacroLoader ) - -void SAL_CALL SfxMacroLoader::initialize( const uno::Sequence<uno::Any>& aArguments ) throw (uno::Exception, uno::RuntimeException) -{ - Reference < XFrame > xFrame; - if ( aArguments.getLength() ) - { - aArguments[0] >>= xFrame; - m_xFrame = xFrame; - } -} - -SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() -{ - SfxObjectShell* pDocShell = NULL; - Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); - if ( xFrame.is() ) - { - SfxFrame* pFrame=0; - for ( pFrame = SfxFrame::GetFirst(); pFrame; pFrame = SfxFrame::GetNext( *pFrame ) ) - { - if ( pFrame->GetFrameInterface() == xFrame ) - break; - } - - if ( pFrame ) - pDocShell = pFrame->GetCurrentDocument(); - } - - return pDocShell; -} - -// ----------------------------------------------------------------------- -uno::Reference<frame::XDispatch> SAL_CALL SfxMacroLoader::queryDispatch( - const util::URL& aURL , - const OUString& /*sTargetFrameName*/, - sal_Int32 /*nSearchFlags*/ ) throw( uno::RuntimeException ) -{ - uno::Reference<frame::XDispatch> xDispatcher; - if(aURL.Complete.startsWith("macro:")) - xDispatcher = this; - return xDispatcher; -} - -// ----------------------------------------------------------------------- -uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL - SfxMacroLoader::queryDispatches( const uno::Sequence < frame::DispatchDescriptor >& seqDescriptor ) - throw( uno::RuntimeException ) -{ - sal_Int32 nCount = seqDescriptor.getLength(); - uno::Sequence< uno::Reference<frame::XDispatch> > lDispatcher(nCount); - for( sal_Int32 i=0; i<nCount; ++i ) - lDispatcher[i] = this->queryDispatch( seqDescriptor[i].FeatureURL, - seqDescriptor[i].FrameName, - seqDescriptor[i].SearchFlags ); - return lDispatcher; -} - -// ----------------------------------------------------------------------- -void SAL_CALL SfxMacroLoader::dispatchWithNotification( - const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& /*lArgs*/, - const uno::Reference<frame::XDispatchResultListener>& xListener ) - throw (uno::RuntimeException) -{ - SolarMutexGuard aGuard; - - uno::Any aAny; - ErrCode nErr = loadMacro( aURL.Complete, aAny, GetObjectShell_Impl() ); - if( xListener.is() ) - { - // always call dispatchFinished(), because we didn't load a document but - // executed a macro instead! - frame::DispatchResultEvent aEvent; - - aEvent.Source = static_cast< ::cppu::OWeakObject* >(this); - if( nErr == ERRCODE_NONE ) - aEvent.State = frame::DispatchResultState::SUCCESS; - else - aEvent.State = frame::DispatchResultState::FAILURE; - - xListener->dispatchFinished( aEvent ) ; - } -} - -uno::Any SAL_CALL SfxMacroLoader::dispatchWithReturnValue( - const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& ) - throw (uno::RuntimeException) -{ - uno::Any aRet; - loadMacro( aURL.Complete, aRet, GetObjectShell_Impl() ); - return aRet; -} - -void SAL_CALL SfxMacroLoader::dispatch( - const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& /*lArgs*/ ) - throw (uno::RuntimeException) -{ - SolarMutexGuard aGuard; - - uno::Any aAny; - loadMacro( aURL.Complete, aAny, GetObjectShell_Impl() ); -} - -void SAL_CALL SfxMacroLoader::addStatusListener( - const uno::Reference< frame::XStatusListener >& , - const util::URL& ) - throw (uno::RuntimeException) -{ - /* TODO - How we can handle different listener for further coming or currently running dispatch() jobs - without any inconsistency! - */ -} - -// ----------------------------------------------------------------------- -void SAL_CALL SfxMacroLoader::removeStatusListener( - const uno::Reference< frame::XStatusListener >&, - const util::URL& ) - throw (uno::RuntimeException) -{ -} - -ErrCode SfxMacroLoader::loadMacro( const OUString& rURL, com::sun::star::uno::Any& rRetval, SfxObjectShell* pSh ) - throw ( uno::RuntimeException ) -{ -#ifdef DISABLE_SCRIPTING - (void) rURL; - (void) rRetval; - (void) pSh; - return ERRCODE_BASIC_PROC_UNDEFINED; -#else - SfxObjectShell* pCurrent = pSh; - if ( !pCurrent ) - // all not full qualified names use the BASIC of the given or current document - pCurrent = SfxObjectShell::Current(); - - // 'macro:///lib.mod.proc(args)' => macro of App-BASIC - // 'macro://[docname|.]/lib.mod.proc(args)' => macro of current or qualified document - // 'macro://obj.method(args)' => direct API call, execute it via App-BASIC - OUString aMacro( rURL ); - sal_Int32 nHashPos = aMacro.indexOf( '/', 8 ); - sal_Int32 nArgsPos = aMacro.indexOf( '(' ); - BasicManager *pAppMgr = SFX_APP()->GetBasicManager(); - BasicManager *pBasMgr = 0; - ErrCode nErr = ERRCODE_NONE; - - // should a macro function be executed ( no direct API call)? - if ( -1 != nHashPos && ( -1 == nArgsPos || nHashPos < nArgsPos ) ) - { - // find BasicManager - SfxObjectShell* pDoc = NULL; - OUString aBasMgrName( INetURLObject::decode(aMacro.copy( 8, nHashPos-8 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET) ); - if ( aBasMgrName.isEmpty() ) - pBasMgr = pAppMgr; - else if ( aBasMgrName == "." ) - { - // current/actual document - pDoc = pCurrent; - if (pDoc) - pBasMgr = pDoc->GetBasicManager(); - } - else - { - // full qualified name, find document by name - for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst(); - pObjSh && !pBasMgr; - pObjSh = SfxObjectShell::GetNext(*pObjSh) ) - if ( aBasMgrName == pObjSh->GetTitle(SFX_TITLE_APINAME) ) - { - pDoc = pObjSh; - pBasMgr = pDoc->GetBasicManager(); - } - } - - if ( pBasMgr ) - { - const bool bIsAppBasic = ( pBasMgr == pAppMgr ); - const bool bIsDocBasic = ( pBasMgr != pAppMgr ); - - if ( pDoc ) - { - // security check for macros from document basic if an SFX doc is given - if ( !pDoc->AdjustMacroMode( OUString() ) ) - // check forbids execution - return ERRCODE_IO_ACCESSDENIED; - } - else if ( pDoc && pDoc->GetMedium() ) - { - pDoc->AdjustMacroMode( OUString() ); - 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 ) - return ERRCODE_IO_ACCESSDENIED; - } - - // find BASIC method - OUString aQualifiedMethod( INetURLObject::decode(aMacro.copy( nHashPos+1 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET) ); - OUString aArgs; - if ( -1 != nArgsPos ) - { - // remove arguments from macro name - aArgs = aQualifiedMethod.copy( nArgsPos - nHashPos - 1 ); - aQualifiedMethod = aQualifiedMethod.copy( 0, nArgsPos - nHashPos - 1 ); - } - - if ( pBasMgr->HasMacro( aQualifiedMethod ) ) - { - Any aOldThisComponent; - const bool bSetDocMacroMode = ( pDoc != NULL ) && bIsDocBasic; - const bool bSetGlobalThisComponent = ( pDoc != NULL ) && bIsAppBasic; - if ( bSetDocMacroMode ) - { - // mark document: it executes an own macro, so it's in a modal mode - pDoc->SetMacroMode_Impl( sal_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 xKeepDocAlive = pDoc; - - { - // 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 ( bSetGlobalThisComponent ) - { - pAppMgr->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); - } - - if ( bSetDocMacroMode ) - { - // remove flag for modal mode - pDoc->SetMacroMode_Impl( sal_False ); - } - } - else - nErr = ERRCODE_BASIC_PROC_UNDEFINED; - } - else - nErr = ERRCODE_IO_NOTEXISTS; - } - else - { - // direct API call on a specified object - OUStringBuffer aCall; - aCall.append('[').append(INetURLObject::decode(aMacro.copy(6), INET_HEX_ESCAPE, - INetURLObject::DECODE_WITH_CHARSET)); - aCall.append(']'); - pAppMgr->GetLib(0)->Execute(aCall.makeStringAndClear()); - nErr = SbxBase::GetError(); - } - - SbxBase::ResetError(); - return nErr; -#endif -} - /* XServiceInfo */ OUString SAL_CALL SfxAppDispatchProvider::getImplementationName() throw( css::uno::RuntimeException ) { @@ -2261,7 +1985,6 @@ SFX2_DLLPUBLIC void* SAL_CALL sfx_component_getFactory( IF_NAME_CREATECOMPONENTFACTORY( BackingComp ) IF_NAME_CREATECOMPONENTFACTORY( SfxGlobalEvents_Impl ) IF_NAME_CREATECOMPONENTFACTORY( SfxFrameLoader_Impl ) - IF_NAME_CREATECOMPONENTFACTORY( SfxMacroLoader ) IF_NAME_CREATECOMPONENTFACTORY( SfxAppDispatchProvider ) IF_NAME_CREATECOMPONENTFACTORY( SfxDocTplService ) IF_NAME_CREATECOMPONENTFACTORY( ShutdownIcon ) diff --git a/sfx2/source/appl/macroloader.cxx b/sfx2/source/appl/macroloader.cxx new file mode 100644 index 000000000000..8d59b8478d90 --- /dev/null +++ b/sfx2/source/appl/macroloader.cxx @@ -0,0 +1,349 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <macroloader.hxx> + +#include <com/sun/star/document/UpdateDocMode.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/frame/DispatchResultState.hpp> +#include <basic/basmgr.hxx> +#include <basic/sbuno.hxx> +#include <cppuhelper/implbase5.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <framework/documentundoguard.hxx> +#include <rtl/ref.hxx> +#include <sfx2/app.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfxsids.hrc> +#include <svl/intitem.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; + +SfxMacroLoader::SfxMacroLoader( const css::uno::Sequence<css::uno::Any>& aArguments ) + throw (css::uno::Exception, css::uno::RuntimeException) +{ + Reference < XFrame > xFrame; + if ( aArguments.getLength() ) + { + aArguments[0] >>= xFrame; + m_xFrame = xFrame; + } +} + +OUString SAL_CALL SfxMacroLoader::getImplementationName() + throw (css::uno::RuntimeException) +{ + return OUString("com.sun.star.comp.sfx2.SfxMacroLoader"); +} + +sal_Bool SAL_CALL SfxMacroLoader::supportsService(OUString const & ServiceName) + throw (css::uno::RuntimeException) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence<OUString> SAL_CALL SfxMacroLoader::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< OUString > aSeq(1); + aSeq[0] = OUString("com.sun.star.frame.ProtocolHandler"); + return aSeq; +} + +SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl() +{ + SfxObjectShell* pDocShell = NULL; + Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY ); + if ( xFrame.is() ) + { + SfxFrame* pFrame=0; + for ( pFrame = SfxFrame::GetFirst(); pFrame; pFrame = SfxFrame::GetNext( *pFrame ) ) + { + if ( pFrame->GetFrameInterface() == xFrame ) + break; + } + + if ( pFrame ) + pDocShell = pFrame->GetCurrentDocument(); + } + + return pDocShell; +} + +// ----------------------------------------------------------------------- +uno::Reference<frame::XDispatch> SAL_CALL SfxMacroLoader::queryDispatch( + const util::URL& aURL , + const OUString& /*sTargetFrameName*/, + sal_Int32 /*nSearchFlags*/ ) throw( uno::RuntimeException ) +{ + uno::Reference<frame::XDispatch> xDispatcher; + if(aURL.Complete.startsWith("macro:")) + xDispatcher = this; + return xDispatcher; +} + +// ----------------------------------------------------------------------- +uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL + SfxMacroLoader::queryDispatches( const uno::Sequence < frame::DispatchDescriptor >& seqDescriptor ) + throw( uno::RuntimeException ) +{ + sal_Int32 nCount = seqDescriptor.getLength(); + uno::Sequence< uno::Reference<frame::XDispatch> > lDispatcher(nCount); + for( sal_Int32 i=0; i<nCount; ++i ) + lDispatcher[i] = this->queryDispatch( seqDescriptor[i].FeatureURL, + seqDescriptor[i].FrameName, + seqDescriptor[i].SearchFlags ); + return lDispatcher; +} + +// ----------------------------------------------------------------------- +void SAL_CALL SfxMacroLoader::dispatchWithNotification( + const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& /*lArgs*/, + const uno::Reference<frame::XDispatchResultListener>& xListener ) + throw (uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + uno::Any aAny; + ErrCode nErr = loadMacro( aURL.Complete, aAny, GetObjectShell_Impl() ); + if( xListener.is() ) + { + // always call dispatchFinished(), because we didn't load a document but + // executed a macro instead! + frame::DispatchResultEvent aEvent; + + aEvent.Source = static_cast< ::cppu::OWeakObject* >(this); + if( nErr == ERRCODE_NONE ) + aEvent.State = frame::DispatchResultState::SUCCESS; + else + aEvent.State = frame::DispatchResultState::FAILURE; + + xListener->dispatchFinished( aEvent ) ; + } +} + +uno::Any SAL_CALL SfxMacroLoader::dispatchWithReturnValue( + const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& ) + throw (uno::RuntimeException) +{ + uno::Any aRet; + loadMacro( aURL.Complete, aRet, GetObjectShell_Impl() ); + return aRet; +} + +void SAL_CALL SfxMacroLoader::dispatch( + const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& /*lArgs*/ ) + throw (uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + uno::Any aAny; + loadMacro( aURL.Complete, aAny, GetObjectShell_Impl() ); +} + +void SAL_CALL SfxMacroLoader::addStatusListener( + const uno::Reference< frame::XStatusListener >& , + const util::URL& ) + throw (uno::RuntimeException) +{ + /* TODO + How we can handle different listener for further coming or currently running dispatch() jobs + without any inconsistency! + */ +} + +// ----------------------------------------------------------------------- +void SAL_CALL SfxMacroLoader::removeStatusListener( + const uno::Reference< frame::XStatusListener >&, + const util::URL& ) + throw (uno::RuntimeException) +{ +} + +ErrCode SfxMacroLoader::loadMacro( const OUString& rURL, com::sun::star::uno::Any& rRetval, SfxObjectShell* pSh ) + throw ( uno::RuntimeException ) +{ +#ifdef DISABLE_SCRIPTING + (void) rURL; + (void) rRetval; + (void) pSh; + return ERRCODE_BASIC_PROC_UNDEFINED; +#else + SfxObjectShell* pCurrent = pSh; + if ( !pCurrent ) + // all not full qualified names use the BASIC of the given or current document + pCurrent = SfxObjectShell::Current(); + + // 'macro:///lib.mod.proc(args)' => macro of App-BASIC + // 'macro://[docname|.]/lib.mod.proc(args)' => macro of current or qualified document + // 'macro://obj.method(args)' => direct API call, execute it via App-BASIC + OUString aMacro( rURL ); + sal_Int32 nHashPos = aMacro.indexOf( '/', 8 ); + sal_Int32 nArgsPos = aMacro.indexOf( '(' ); + BasicManager *pAppMgr = SFX_APP()->GetBasicManager(); + BasicManager *pBasMgr = 0; + ErrCode nErr = ERRCODE_NONE; + + // should a macro function be executed ( no direct API call)? + if ( -1 != nHashPos && ( -1 == nArgsPos || nHashPos < nArgsPos ) ) + { + // find BasicManager + SfxObjectShell* pDoc = NULL; + OUString aBasMgrName( INetURLObject::decode(aMacro.copy( 8, nHashPos-8 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET) ); + if ( aBasMgrName.isEmpty() ) + pBasMgr = pAppMgr; + else if ( aBasMgrName == "." ) + { + // current/actual document + pDoc = pCurrent; + if (pDoc) + pBasMgr = pDoc->GetBasicManager(); + } + else + { + // full qualified name, find document by name + for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst(); + pObjSh && !pBasMgr; + pObjSh = SfxObjectShell::GetNext(*pObjSh) ) + if ( aBasMgrName == pObjSh->GetTitle(SFX_TITLE_APINAME) ) + { + pDoc = pObjSh; + pBasMgr = pDoc->GetBasicManager(); + } + } + + if ( pBasMgr ) + { + const bool bIsAppBasic = ( pBasMgr == pAppMgr ); + const bool bIsDocBasic = ( pBasMgr != pAppMgr ); + + if ( pDoc ) + { + // security check for macros from document basic if an SFX doc is given + if ( !pDoc->AdjustMacroMode( OUString() ) ) + // check forbids execution + return ERRCODE_IO_ACCESSDENIED; + } + else if ( pDoc && pDoc->GetMedium() ) + { + pDoc->AdjustMacroMode( OUString() ); + 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 ) + return ERRCODE_IO_ACCESSDENIED; + } + + // find BASIC method + OUString aQualifiedMethod( INetURLObject::decode(aMacro.copy( nHashPos+1 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET) ); + OUString aArgs; + if ( -1 != nArgsPos ) + { + // remove arguments from macro name + aArgs = aQualifiedMethod.copy( nArgsPos - nHashPos - 1 ); + aQualifiedMethod = aQualifiedMethod.copy( 0, nArgsPos - nHashPos - 1 ); + } + + if ( pBasMgr->HasMacro( aQualifiedMethod ) ) + { + Any aOldThisComponent; + const bool bSetDocMacroMode = ( pDoc != NULL ) && bIsDocBasic; + const bool bSetGlobalThisComponent = ( pDoc != NULL ) && bIsAppBasic; + if ( bSetDocMacroMode ) + { + // mark document: it executes an own macro, so it's in a modal mode + pDoc->SetMacroMode_Impl( sal_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 xKeepDocAlive = pDoc; + + { + // 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 ( bSetGlobalThisComponent ) + { + pAppMgr->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); + } + + if ( bSetDocMacroMode ) + { + // remove flag for modal mode + pDoc->SetMacroMode_Impl( sal_False ); + } + } + else + nErr = ERRCODE_BASIC_PROC_UNDEFINED; + } + else + nErr = ERRCODE_IO_NOTEXISTS; + } + else + { + // direct API call on a specified object + OUStringBuffer aCall; + aCall.append('[').append(INetURLObject::decode(aMacro.copy(6), INET_HEX_ESCAPE, + INetURLObject::DECODE_WITH_CHARSET)); + aCall.append(']'); + pAppMgr->GetLib(0)->Execute(aCall.makeStringAndClear()); + nErr = SbxBase::GetError(); + } + + SbxBase::ResetError(); + return nErr; +#endif +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL +com_sun_star_comp_sfx2_SfxMacroLoader_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &arguments) +{ + rtl::Reference<SfxMacroLoader> x(new SfxMacroLoader(arguments)); + x->acquire(); + return static_cast<cppu::OWeakObject *>(x.get()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/inc/macroloader.hxx b/sfx2/source/inc/macroloader.hxx new file mode 100644 index 000000000000..8e632e5024e8 --- /dev/null +++ b/sfx2/source/inc/macroloader.hxx @@ -0,0 +1,94 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SFXMACROLOADER_HXX +#define INCLUDED_SFXMACROLOADER_HXX + +#include <sal/config.h> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/DispatchDescriptor.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XNotifyingDispatch.hpp> +#include <com/sun/star/frame/XDispatchResultListener.hpp> +#include <com/sun/star/frame/XSynchronousDispatch.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/util/URL.hpp> + +#include <cppuhelper/implbase4.hxx> +#include <sfx2/sfxuno.hxx> +#include <tools/errcode.hxx> + +class SfxObjectShell; + +class SfxMacroLoader : public cppu::WeakImplHelper4< + css::frame::XDispatchProvider, + css::frame::XNotifyingDispatch, + css::frame::XSynchronousDispatch, + css::lang::XServiceInfo> +{ + css::uno::WeakReference < css::frame::XFrame > m_xFrame; + SfxObjectShell* GetObjectShell_Impl(); + +public: + SfxMacroLoader(const css::uno::Sequence< css::uno::Any >& aArguments ) + throw (css::uno::Exception, css::uno::RuntimeException); + + virtual OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw (css::uno::RuntimeException); + + static ErrCode loadMacro( const OUString& aURL, css::uno::Any& rRetval, SfxObjectShell* pDoc=NULL ) throw( css::uno::RuntimeException ); + + virtual css::uno::Reference < css::frame::XDispatch > SAL_CALL queryDispatch( + const css::util::URL& aURL, const OUString& sTargetFrameName, + FrameSearchFlags eSearchFlags ) + throw( css::uno::RuntimeException ); + + virtual css::uno::Sequence< css::uno::Reference < css::frame::XDispatch > > SAL_CALL queryDispatches( + const css::uno::Sequence < css::frame::DispatchDescriptor >& seqDescriptor ) + throw( css::uno::RuntimeException ); + + virtual void SAL_CALL dispatchWithNotification( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& lArgs, const css::uno::Reference< css::frame::XDispatchResultListener >& Listener ) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& lArgs ) + throw (css::uno::RuntimeException); + + virtual css::uno::Any SAL_CALL dispatchWithReturnValue( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& lArgs ) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl, const css::util::URL& aURL ) + throw (css::uno::RuntimeException); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/notify/eventsupplier.cxx b/sfx2/source/notify/eventsupplier.cxx index 3a12c9e1e281..418f35d3b867 100644 --- a/sfx2/source/notify/eventsupplier.cxx +++ b/sfx2/source/notify/eventsupplier.cxx @@ -28,7 +28,6 @@ #include <tools/urlobj.hxx> #include <tools/diagnose_ex.h> #include <svl/macitem.hxx> -#include <sfx2/appuno.hxx> #include <sfx2/objsh.hxx> #include <sfx2/sfxbasemodel.hxx> #include <sfx2/evntconf.hxx> @@ -47,6 +46,7 @@ #include <sfx2/docfile.hxx> #include <sfx2/viewfrm.hxx> #include <sfx2/frame.hxx> +#include <macroloader.hxx> //-------------------------------------------------------------------------------------------------------- diff --git a/sfx2/util/sfx.component b/sfx2/util/sfx.component index c5f25150de5e..4d47644c72a6 100644 --- a/sfx2/util/sfx.component +++ b/sfx2/util/sfx.component @@ -66,7 +66,8 @@ <implementation name="com.sun.star.comp.sfx2.PluginObject"> <service name="com.sun.star.frame.SpecialEmbeddedObject"/> </implementation> - <implementation name="com.sun.star.comp.sfx2.SfxMacroLoader"> + <implementation name="com.sun.star.comp.sfx2.SfxMacroLoader" + constructor="com_sun_star_comp_sfx2_SfxMacroLoader_get_implementation"> <service name="com.sun.star.frame.ProtocolHandler"/> </implementation> </component> |