LCOV - code coverage report
Current view: top level - sfx2/source/appl - macroloader.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 27 134 20.1 %
Date: 2015-06-13 12:38:46 Functions: 6 14 42.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : 
      22             : #include <macroloader.hxx>
      23             : 
      24             : #include <com/sun/star/document/UpdateDocMode.hpp>
      25             : #include <com/sun/star/document/MacroExecMode.hpp>
      26             : #include <com/sun/star/frame/DispatchResultState.hpp>
      27             : #include <basic/basmgr.hxx>
      28             : #include <basic/sbuno.hxx>
      29             : #include <cppuhelper/implbase5.hxx>
      30             : #include <cppuhelper/supportsservice.hxx>
      31             : #include <framework/documentundoguard.hxx>
      32             : #include <rtl/ref.hxx>
      33             : #include <sfx2/app.hxx>
      34             : #include <sfx2/docfile.hxx>
      35             : #include <sfx2/frame.hxx>
      36             : #include <sfx2/objsh.hxx>
      37             : #include <sfx2/request.hxx>
      38             : #include <sfx2/sfxsids.hrc>
      39             : #include <svl/intitem.hxx>
      40             : #include <tools/urlobj.hxx>
      41             : #include <vcl/svapp.hxx>
      42             : 
      43             : #include <boost/scoped_ptr.hpp>
      44             : 
      45             : using namespace ::com::sun::star;
      46             : using namespace ::com::sun::star::frame;
      47             : using namespace ::com::sun::star::lang;
      48             : using namespace ::com::sun::star::uno;
      49             : using namespace ::com::sun::star::util;
      50             : 
      51           2 : SfxMacroLoader::SfxMacroLoader(const css::uno::Sequence< css::uno::Any >& aArguments)
      52           2 :     throw (css::uno::Exception, css::uno::RuntimeException)
      53             : {
      54           2 :     Reference < XFrame > xFrame;
      55           2 :     if ( aArguments.getLength() )
      56             :     {
      57           0 :         aArguments[0] >>= xFrame;
      58           0 :         m_xFrame = xFrame;
      59           2 :     }
      60           2 : }
      61             : 
      62           2 : OUString SAL_CALL SfxMacroLoader::getImplementationName()
      63             :     throw (css::uno::RuntimeException, std::exception)
      64             : {
      65           2 :     return OUString("com.sun.star.comp.sfx2.SfxMacroLoader");
      66             : }
      67             : 
      68           0 : sal_Bool SAL_CALL SfxMacroLoader::supportsService(OUString const & ServiceName)
      69             :     throw (css::uno::RuntimeException, std::exception)
      70             : {
      71           0 :     return cppu::supportsService(this, ServiceName);
      72             : }
      73             : 
      74           1 : css::uno::Sequence<OUString> SAL_CALL SfxMacroLoader::getSupportedServiceNames()
      75             :     throw (css::uno::RuntimeException, std::exception)
      76             : {
      77           1 :     css::uno::Sequence< OUString > aSeq(1);
      78           1 :     aSeq[0] = "com.sun.star.frame.ProtocolHandler";
      79           1 :     return aSeq;
      80             : }
      81             : 
      82           0 : SfxObjectShell* SfxMacroLoader::GetObjectShell_Impl()
      83             : {
      84           0 :     SfxObjectShell* pDocShell = NULL;
      85           0 :     Reference < XFrame > xFrame( m_xFrame.get(), UNO_QUERY );
      86           0 :     if ( xFrame.is() )
      87             :     {
      88           0 :         SfxFrame* pFrame=0;
      89           0 :         for ( pFrame = SfxFrame::GetFirst(); pFrame; pFrame = SfxFrame::GetNext( *pFrame ) )
      90             :         {
      91           0 :             if ( pFrame->GetFrameInterface() == xFrame )
      92           0 :                 break;
      93             :         }
      94             : 
      95           0 :         if ( pFrame )
      96           0 :             pDocShell = pFrame->GetCurrentDocument();
      97             :     }
      98             : 
      99           0 :     return pDocShell;
     100             : }
     101             : 
     102             : 
     103           3 : uno::Reference<frame::XDispatch> SAL_CALL SfxMacroLoader::queryDispatch(
     104             :     const util::URL&   aURL            ,
     105             :     const OUString&               /*sTargetFrameName*/,
     106             :     sal_Int32                            /*nSearchFlags*/    ) throw( uno::RuntimeException, std::exception )
     107             : {
     108           3 :     uno::Reference<frame::XDispatch> xDispatcher;
     109           3 :     if(aURL.Complete.startsWith("macro:"))
     110           3 :         xDispatcher = this;
     111           3 :     return xDispatcher;
     112             : }
     113             : 
     114             : 
     115             : uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL
     116           1 :                 SfxMacroLoader::queryDispatches( const uno::Sequence < frame::DispatchDescriptor >& seqDescriptor )
     117             :                     throw( uno::RuntimeException, std::exception )
     118             : {
     119           1 :     sal_Int32 nCount = seqDescriptor.getLength();
     120           1 :     uno::Sequence< uno::Reference<frame::XDispatch> > lDispatcher(nCount);
     121           3 :     for( sal_Int32 i=0; i<nCount; ++i )
     122           6 :         lDispatcher[i] = this->queryDispatch( seqDescriptor[i].FeatureURL,
     123           2 :                                               seqDescriptor[i].FrameName,
     124           4 :                                               seqDescriptor[i].SearchFlags );
     125           1 :     return lDispatcher;
     126             : }
     127             : 
     128             : 
     129           0 : void SAL_CALL SfxMacroLoader::dispatchWithNotification(
     130             :     const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& /*lArgs*/,
     131             :     const uno::Reference<frame::XDispatchResultListener>& xListener )
     132             :               throw (uno::RuntimeException, std::exception)
     133             : {
     134           0 :     SolarMutexGuard aGuard;
     135             : 
     136           0 :     uno::Any aAny;
     137           0 :     ErrCode nErr = loadMacro( aURL.Complete, aAny, GetObjectShell_Impl() );
     138           0 :     if( xListener.is() )
     139             :     {
     140             :         // always call dispatchFinished(), because we didn't load a document but
     141             :         // executed a macro instead!
     142           0 :         frame::DispatchResultEvent aEvent;
     143             : 
     144           0 :         aEvent.Source = static_cast< ::cppu::OWeakObject* >(this);
     145           0 :         if( nErr == ERRCODE_NONE )
     146           0 :             aEvent.State = frame::DispatchResultState::SUCCESS;
     147             :         else
     148           0 :             aEvent.State = frame::DispatchResultState::FAILURE;
     149             : 
     150           0 :         xListener->dispatchFinished( aEvent ) ;
     151           0 :     }
     152           0 : }
     153             : 
     154           0 : uno::Any SAL_CALL SfxMacroLoader::dispatchWithReturnValue(
     155             :     const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& )
     156             :         throw (uno::RuntimeException, std::exception)
     157             : {
     158           0 :     uno::Any aRet;
     159           0 :     loadMacro( aURL.Complete, aRet, GetObjectShell_Impl() );
     160           0 :     return aRet;
     161             : }
     162             : 
     163           0 : void SAL_CALL SfxMacroLoader::dispatch(
     164             :     const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& /*lArgs*/ )
     165             :         throw (uno::RuntimeException, std::exception)
     166             : {
     167           0 :     SolarMutexGuard aGuard;
     168             : 
     169           0 :     uno::Any aAny;
     170           0 :     loadMacro( aURL.Complete, aAny, GetObjectShell_Impl() );
     171           0 : }
     172             : 
     173           0 : void SAL_CALL SfxMacroLoader::addStatusListener(
     174             :     const uno::Reference< frame::XStatusListener >& ,
     175             :     const util::URL&                                                    )
     176             :               throw (uno::RuntimeException, std::exception)
     177             : {
     178             :     /* TODO
     179             :             How we can handle different listener for further coming or currently running dispatch() jobs
     180             :             without any inconsistency!
     181             :      */
     182           0 : }
     183             : 
     184             : 
     185           0 : void SAL_CALL SfxMacroLoader::removeStatusListener(
     186             :     const uno::Reference< frame::XStatusListener >&,
     187             :     const util::URL&                                                  )
     188             :         throw (uno::RuntimeException, std::exception)
     189             : {
     190           0 : }
     191             : 
     192           0 : ErrCode SfxMacroLoader::loadMacro( const OUString& rURL, com::sun::star::uno::Any& rRetval, SfxObjectShell* pSh )
     193             :     throw ( ucb::ContentCreationException, uno::RuntimeException )
     194             : {
     195             : #if !HAVE_FEATURE_SCRIPTING
     196             :     (void) rURL;
     197             :     (void) rRetval;
     198             :     (void) pSh;
     199             :     return ERRCODE_BASIC_PROC_UNDEFINED;
     200             : #else
     201           0 :     SfxObjectShell* pCurrent = pSh;
     202           0 :     if ( !pCurrent )
     203             :         // all not full qualified names use the BASIC of the given or current document
     204           0 :         pCurrent = SfxObjectShell::Current();
     205             : 
     206             :     // 'macro:///lib.mod.proc(args)' => macro of App-BASIC
     207             :     // 'macro://[docname|.]/lib.mod.proc(args)' => macro of current or qualified document
     208             :     // 'macro://obj.method(args)' => direct API call, execute it via App-BASIC
     209           0 :     OUString aMacro( rURL );
     210           0 :     sal_Int32 nHashPos = aMacro.indexOf( '/', 8 );
     211           0 :     sal_Int32 nArgsPos = aMacro.indexOf( '(' );
     212           0 :     BasicManager *pAppMgr = SfxApplication::GetBasicManager();
     213           0 :     BasicManager *pBasMgr = 0;
     214           0 :     ErrCode nErr = ERRCODE_NONE;
     215             : 
     216             :     // should a macro function be executed ( no direct API call)?
     217           0 :     if ( -1 != nHashPos && ( -1 == nArgsPos || nHashPos < nArgsPos ) )
     218             :     {
     219             :         // find BasicManager
     220           0 :         SfxObjectShell* pDoc = NULL;
     221           0 :         OUString aBasMgrName( INetURLObject::decode(aMacro.copy( 8, nHashPos-8 ), INetURLObject::DECODE_WITH_CHARSET) );
     222           0 :         if ( aBasMgrName.isEmpty() )
     223           0 :             pBasMgr = pAppMgr;
     224           0 :         else if ( aBasMgrName == "." )
     225             :         {
     226             :             // current/actual document
     227           0 :             pDoc = pCurrent;
     228           0 :             if (pDoc)
     229           0 :                 pBasMgr = pDoc->GetBasicManager();
     230             :         }
     231             :         else
     232             :         {
     233             :             // full qualified name, find document by name
     234           0 :             for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
     235           0 :                     pObjSh && !pBasMgr;
     236             :                     pObjSh = SfxObjectShell::GetNext(*pObjSh) )
     237           0 :                 if ( aBasMgrName == pObjSh->GetTitle(SFX_TITLE_APINAME) )
     238             :                 {
     239           0 :                     pDoc = pObjSh;
     240           0 :                     pBasMgr = pDoc->GetBasicManager();
     241             :                 }
     242             :         }
     243             : 
     244           0 :         if ( pBasMgr )
     245             :         {
     246           0 :             const bool bIsAppBasic = ( pBasMgr == pAppMgr );
     247           0 :             const bool bIsDocBasic = ( pBasMgr != pAppMgr );
     248             : 
     249           0 :             if ( pDoc )
     250             :             {
     251             :                 // security check for macros from document basic if an SFX doc is given
     252           0 :                 if ( !pDoc->AdjustMacroMode( OUString() ) )
     253             :                     // check forbids execution
     254           0 :                     return ERRCODE_IO_ACCESSDENIED;
     255             :             }
     256             : 
     257             :             // find BASIC method
     258           0 :             OUString aQualifiedMethod( INetURLObject::decode(aMacro.copy( nHashPos+1 ), INetURLObject::DECODE_WITH_CHARSET) );
     259           0 :             OUString aArgs;
     260           0 :             if ( -1 != nArgsPos )
     261             :             {
     262             :                 // remove arguments from macro name
     263           0 :                 aArgs = aQualifiedMethod.copy( nArgsPos - nHashPos - 1 );
     264           0 :                 aQualifiedMethod = aQualifiedMethod.copy( 0, nArgsPos - nHashPos - 1 );
     265             :             }
     266             : 
     267           0 :             if ( pBasMgr->HasMacro( aQualifiedMethod ) )
     268             :             {
     269           0 :                 Any aOldThisComponent;
     270           0 :                 const bool bSetDocMacroMode = ( pDoc != NULL ) && bIsDocBasic;
     271           0 :                 const bool bSetGlobalThisComponent = ( pDoc != NULL ) && bIsAppBasic;
     272           0 :                 if ( bSetDocMacroMode )
     273             :                 {
     274             :                     // mark document: it executes an own macro, so it's in a modal mode
     275           0 :                     pDoc->SetMacroMode_Impl( true );
     276             :                 }
     277             : 
     278           0 :                 if ( bSetGlobalThisComponent )
     279             :                 {
     280             :                     // document is executed via AppBASIC, adjust ThisComponent variable
     281           0 :                     aOldThisComponent = pAppMgr->SetGlobalUNOConstant( "ThisComponent", makeAny( pDoc->GetModel() ) );
     282             :                 }
     283             : 
     284             :                 // just to let the shell be alive
     285           0 :                 SfxObjectShellRef xKeepDocAlive = pDoc;
     286             : 
     287             :                 {
     288             :                     // attempt to protect the document against the script tampering with its Undo Context
     289           0 :                     boost::scoped_ptr< ::framework::DocumentUndoGuard > pUndoGuard;
     290           0 :                     if ( bIsDocBasic )
     291           0 :                         pUndoGuard.reset( new ::framework::DocumentUndoGuard( pDoc->GetModel() ) );
     292             : 
     293             :                     // execute the method
     294           0 :                     SbxVariableRef retValRef = new SbxVariable;
     295           0 :                     nErr = pBasMgr->ExecuteMacro( aQualifiedMethod, aArgs, retValRef );
     296           0 :                     if ( nErr == ERRCODE_NONE )
     297           0 :                         rRetval = sbxToUnoValue( retValRef );
     298             :                 }
     299             : 
     300           0 :                 if ( bSetGlobalThisComponent )
     301             :                 {
     302           0 :                     pAppMgr->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent );
     303             :                 }
     304             : 
     305           0 :                 if ( bSetDocMacroMode )
     306             :                 {
     307             :                     // remove flag for modal mode
     308           0 :                     pDoc->SetMacroMode_Impl( false );
     309           0 :                 }
     310             :             }
     311             :             else
     312           0 :                 nErr = ERRCODE_BASIC_PROC_UNDEFINED;
     313             :         }
     314             :         else
     315           0 :             nErr = ERRCODE_IO_NOTEXISTS;
     316             :     }
     317             :     else
     318             :     {
     319             :         // direct API call on a specified object
     320           0 :         OUStringBuffer aCall;
     321           0 :         aCall.append('[').append(INetURLObject::decode(aMacro.copy(6),
     322           0 :             INetURLObject::DECODE_WITH_CHARSET));
     323           0 :         aCall.append(']');
     324           0 :         pAppMgr->GetLib(0)->Execute(aCall.makeStringAndClear());
     325           0 :         nErr = SbxBase::GetError();
     326             :     }
     327             : 
     328           0 :     SbxBase::ResetError();
     329           0 :     return nErr;
     330             : #endif
     331             : }
     332             : 
     333             : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
     334           2 : com_sun_star_comp_sfx2_SfxMacroLoader_get_implementation(
     335             :     css::uno::XComponentContext *,
     336             :     css::uno::Sequence<css::uno::Any> const &arguments)
     337             : {
     338           2 :     return cppu::acquire(new SfxMacroLoader(arguments));
     339             : }
     340             : 
     341             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11