update dev300-m58
[ooovba.git] / sfx2 / source / doc / docmacromode.cxx
blobfc462bc137aa97ebc7014a9da0c8265f22177074
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docmacromode.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include "sfx2/docmacromode.hxx"
35 #include "sfx2/signaturestate.hxx"
37 /** === begin UNO includes === **/
38 #include <com/sun/star/document/MacroExecMode.hpp>
39 #include <com/sun/star/task/ErrorCodeRequest.hpp>
40 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
41 #include <com/sun/star/task/InteractionClassification.hpp>
42 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
43 #include <com/sun/star/script/XLibraryQueryExecutable.hpp>
44 /** === end UNO includes === **/
46 #include <comphelper/componentcontext.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <framework/interaction.hxx>
49 #include <osl/file.hxx>
50 #include <rtl/ref.hxx>
51 #include <svtools/securityoptions.hxx>
52 #include <svtools/sfxecode.hxx>
53 #include <tools/diagnose_ex.h>
54 #include <tools/urlobj.hxx>
56 //........................................................................
57 namespace sfx2
59 //........................................................................
61 /** === begin UNO using === **/
62 using ::com::sun::star::uno::Reference;
63 using ::com::sun::star::task::XInteractionHandler;
64 using ::com::sun::star::uno::Any;
65 using ::com::sun::star::task::XInteractionHandler;
66 using ::com::sun::star::uno::Sequence;
67 using ::com::sun::star::task::XInteractionContinuation;
68 using ::com::sun::star::task::XInteractionRequest;
69 using ::com::sun::star::task::DocumentMacroConfirmationRequest;
70 using ::com::sun::star::task::ErrorCodeRequest;
71 using ::com::sun::star::uno::Exception;
72 using ::com::sun::star::security::XDocumentDigitalSignatures;
73 using ::com::sun::star::security::DocumentSignatureInformation;
74 using ::com::sun::star::embed::XStorage;
75 using ::com::sun::star::task::InteractionClassification_QUERY;
76 using ::com::sun::star::document::XEmbeddedScripts;
77 using ::com::sun::star::uno::UNO_SET_THROW;
78 using ::com::sun::star::script::XLibraryContainer;
79 using ::com::sun::star::script::XLibraryQueryExecutable;
80 using ::com::sun::star::container::XNameAccess;
81 using ::com::sun::star::uno::UNO_QUERY_THROW;
82 using ::com::sun::star::uno::UNO_QUERY;
83 /** === end UNO using === **/
84 namespace MacroExecMode = ::com::sun::star::document::MacroExecMode;
86 //====================================================================
87 //= DocumentMacroMode_Data
88 //====================================================================
89 struct DocumentMacroMode_Data
91 IMacroDocumentAccess& rDocumentAccess;
92 sal_Bool bMacroDisabledMessageShown;
93 sal_Bool bDocMacroDisabledMessageShown;
95 DocumentMacroMode_Data( IMacroDocumentAccess& _rDocumentAccess )
96 :rDocumentAccess( _rDocumentAccess )
97 ,bMacroDisabledMessageShown( sal_False )
98 ,bDocMacroDisabledMessageShown( sal_False )
103 //====================================================================
104 //= helper
105 //====================================================================
106 namespace
108 //................................................................
109 /** calls the given interaction handler with the given interaction request, offering
110 the two continuations "Approve" and "Abort"
112 @return
113 <TRUE/> if and only if the given handler handled the the request, and the "Approve"
114 continuation was selected.
116 sal_Bool lcl_callInterActionHandler( const Reference< XInteractionHandler >& _rxHandler, const Any& _rRequest )
118 if ( !_rxHandler.is() )
119 return sal_False;
123 Sequence< Reference< XInteractionContinuation > > aContinuations(2);
125 ::rtl::Reference< ::framework::ContinuationAbort > pAbort( new ::framework::ContinuationAbort() );
126 aContinuations[ 0 ] = pAbort.get();
128 ::rtl::Reference< ::framework::ContinuationApprove > pApprove( new ::framework::ContinuationApprove() );
129 aContinuations[ 1 ] = pApprove.get();
131 Reference< XInteractionRequest > xRequest( new ::framework::InteractionRequest( _rRequest, aContinuations ) );
132 _rxHandler->handle( xRequest );
134 if ( pApprove->isSelected() )
135 return sal_True;
137 catch( const Exception& )
139 DBG_UNHANDLED_EXCEPTION();
141 return sal_False;
144 //................................................................
145 void lcl_showGeneralSfxErrorOnce( const Reference< XInteractionHandler >& _rxHandler, const sal_Int32 _nSfxErrorCode, sal_Bool& _rbAlreadyShown )
147 if ( _rbAlreadyShown )
148 return;
150 ErrorCodeRequest aErrorCodeRequest;
151 aErrorCodeRequest.ErrCode = _nSfxErrorCode;
153 _rbAlreadyShown = lcl_callInterActionHandler( _rxHandler, makeAny( aErrorCodeRequest ) );
156 //................................................................
157 void lcl_showMacrosDisabledError( const Reference< XInteractionHandler >& _rxHandler, sal_Bool& _rbAlreadyShown )
159 lcl_showGeneralSfxErrorOnce( _rxHandler, ERRCODE_SFX_MACROS_SUPPORT_DISABLED, _rbAlreadyShown );
162 //................................................................
163 void lcl_showDocumentMacrosDisabledError( const Reference< XInteractionHandler >& _rxHandler, sal_Bool& _rbAlreadyShown )
165 lcl_showGeneralSfxErrorOnce( _rxHandler, ERRCODE_SFX_DOCUMENT_MACRO_DISABLED, _rbAlreadyShown );
168 //................................................................
169 sal_Bool lcl_showMacroWarning( const Reference< XInteractionHandler >& _rxHandler,
170 const ::rtl::OUString& _rDocumentLocation )
172 DocumentMacroConfirmationRequest aRequest;
173 aRequest.DocumentURL = _rDocumentLocation;
174 return lcl_callInterActionHandler( _rxHandler, makeAny( aRequest ) );
177 //................................................................
178 sal_Bool lcl_showMacroWarning( const Reference< XInteractionHandler >& _rxHandler,
179 const ::rtl::OUString& _rDocumentLocation, const Reference< XStorage >& _rxDocStor,
180 const Sequence< DocumentSignatureInformation >& _rDocSigInfo )
182 DocumentMacroConfirmationRequest aRequest;
183 aRequest.DocumentURL = _rDocumentLocation;
184 aRequest.DocumentStorage = _rxDocStor;
185 aRequest.DocumentSignatureInformation = _rDocSigInfo;
186 aRequest.Classification = InteractionClassification_QUERY;
187 return lcl_callInterActionHandler( _rxHandler, makeAny( aRequest ) );
191 //====================================================================
192 //= DocumentMacroMode
193 //====================================================================
194 //--------------------------------------------------------------------
195 DocumentMacroMode::DocumentMacroMode( IMacroDocumentAccess& _rDocumentAccess )
196 :m_pData( new DocumentMacroMode_Data( _rDocumentAccess ) )
200 //--------------------------------------------------------------------
201 DocumentMacroMode::~DocumentMacroMode()
205 //--------------------------------------------------------------------
206 sal_Bool DocumentMacroMode::allowMacroExecution()
208 m_pData->rDocumentAccess.setCurrentMacroExecMode( MacroExecMode::ALWAYS_EXECUTE_NO_WARN );
209 return sal_True;
212 //--------------------------------------------------------------------
213 sal_Bool DocumentMacroMode::disallowMacroExecution()
215 m_pData->rDocumentAccess.setCurrentMacroExecMode( MacroExecMode::NEVER_EXECUTE );
216 return sal_False;
219 //--------------------------------------------------------------------
220 sal_Bool DocumentMacroMode::adjustMacroMode( const Reference< XInteractionHandler >& _rxInteraction )
222 sal_uInt16 nMacroExecutionMode = m_pData->rDocumentAccess.getCurrentMacroExecMode();
224 if ( SvtSecurityOptions().IsMacroDisabled() )
226 // no macro should be executed at all
227 lcl_showMacrosDisabledError( _rxInteraction, m_pData->bMacroDisabledMessageShown );
228 return disallowMacroExecution();
231 // get setting from configuration if required
232 enum AutoConfirmation
234 eNoAutoConfirm,
235 eAutoConfirmApprove,
236 eAutoConfirmReject
238 AutoConfirmation eAutoConfirm( eNoAutoConfirm );
240 if ( ( nMacroExecutionMode == MacroExecMode::USE_CONFIG )
241 || ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION )
242 || ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION )
245 SvtSecurityOptions aOpt;
246 switch ( aOpt.GetMacroSecurityLevel() )
248 case 3:
249 nMacroExecutionMode = MacroExecMode::FROM_LIST_NO_WARN;
250 break;
251 case 2:
252 nMacroExecutionMode = MacroExecMode::FROM_LIST_AND_SIGNED_WARN;
253 break;
254 case 1:
255 nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE;
256 break;
257 case 0:
258 nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
259 break;
260 default:
261 OSL_ENSURE( sal_False, "DocumentMacroMode::adjustMacroMode: unexpected macro security level!" );
262 nMacroExecutionMode = MacroExecMode::NEVER_EXECUTE;
265 if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION )
266 eAutoConfirm = eAutoConfirmReject;
267 else if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION )
268 eAutoConfirm = eAutoConfirmApprove;
271 if ( nMacroExecutionMode == MacroExecMode::NEVER_EXECUTE )
272 return sal_False;
274 if ( nMacroExecutionMode == MacroExecMode::ALWAYS_EXECUTE_NO_WARN )
275 return sal_True;
279 ::rtl::OUString sReferrer( m_pData->rDocumentAccess.getDocumentLocation() );
281 // get document location from medium name and check whether it is a trusted one
282 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
283 Reference< XDocumentDigitalSignatures > xSignatures;
284 if ( aContext.createComponent( "com.sun.star.security.DocumentDigitalSignatures", xSignatures ) )
286 INetURLObject aURLReferer( sReferrer );
288 ::rtl::OUString aLocation;
289 if ( aURLReferer.removeSegment() )
290 aLocation = aURLReferer.GetMainURL( INetURLObject::NO_DECODE );
292 if ( aLocation.getLength() && xSignatures->isLocationTrusted( aLocation ) )
294 return allowMacroExecution();
298 // at this point it is clear that the document is not in the secure location
299 if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN )
301 lcl_showDocumentMacrosDisabledError( _rxInteraction, m_pData->bDocMacroDisabledMessageShown );
302 return disallowMacroExecution();
305 // check whether the document is signed with trusted certificate
306 if ( xSignatures.is() && nMacroExecutionMode != MacroExecMode::FROM_LIST )
308 Sequence< DocumentSignatureInformation > aScriptingSignatureInformations;
309 Reference < XStorage > xStore( m_pData->rDocumentAccess.getLastCommitDocumentStorage() );
311 sal_uInt16 nSignatureState = m_pData->rDocumentAccess.getScriptingSignatureState();
312 if ( nSignatureState == SIGNATURESTATE_SIGNATURES_BROKEN )
314 if ( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
316 m_pData->rDocumentAccess.showBrokenSignatureWarning( _rxInteraction );
317 return disallowMacroExecution();
320 else
322 if ( ( ( nSignatureState == SIGNATURESTATE_SIGNATURES_OK )
323 || ( nSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED )
325 && xStore.is()
328 aScriptingSignatureInformations =
329 xSignatures->verifyScriptingContentSignatures( xStore, NULL );
333 sal_Int32 nNumOfInfos = aScriptingSignatureInformations.getLength();
335 // from now on sReferrer is the system file path
336 // sReferrer = INetURLObject::decode( sReferrer, '%', INetURLObject::DECODE_WITH_CHARSET );
337 ::rtl::OUString aSystemFileURL;
338 if ( osl::FileBase::getSystemPathFromFileURL( sReferrer, aSystemFileURL ) == osl::FileBase::E_None )
339 sReferrer = aSystemFileURL;
341 if ( nNumOfInfos )
343 for ( sal_Int32 i = 0; i < nNumOfInfos; i++ )
344 if ( xSignatures->isAuthorTrusted( aScriptingSignatureInformations[i].Signer ) )
346 // there's at least one author we trust which signed the doc
347 return allowMacroExecution();
350 if ( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
352 sal_Bool bApproved = lcl_showMacroWarning( _rxInteraction,
353 sReferrer, xStore, aScriptingSignatureInformations );
354 return ( bApproved ? allowMacroExecution() : disallowMacroExecution() );
359 // at this point it is clear that the document is neither in secure location nor signed with trusted certificate
360 if ( ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
361 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
364 if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
366 lcl_showDocumentMacrosDisabledError( _rxInteraction, m_pData->bDocMacroDisabledMessageShown );
368 return disallowMacroExecution();
371 catch ( Exception& )
373 if ( ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN )
374 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
375 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
378 return disallowMacroExecution();
382 // conformation is required
383 sal_Bool bSecure = sal_False;
385 if ( eAutoConfirm == eNoAutoConfirm )
387 ::rtl::OUString sReferrer( m_pData->rDocumentAccess.getDocumentLocation() );
389 ::rtl::OUString aSystemFileURL;
390 if ( osl::FileBase::getSystemPathFromFileURL( sReferrer, aSystemFileURL ) == osl::FileBase::E_None )
391 sReferrer = aSystemFileURL;
393 bSecure = lcl_showMacroWarning( _rxInteraction, sReferrer );
395 else
396 bSecure = ( eAutoConfirm == eAutoConfirmApprove );
398 return ( bSecure ? allowMacroExecution() : disallowMacroExecution() );
401 //--------------------------------------------------------------------
402 sal_Bool DocumentMacroMode::isMacroExecutionDisallowed() const
404 return m_pData->rDocumentAccess.getCurrentMacroExecMode() == MacroExecMode::NEVER_EXECUTE;
407 //--------------------------------------------------------------------
408 sal_Bool DocumentMacroMode::hasMacroLibrary() const
410 sal_Bool bHasMacroLib = sal_False;
413 Reference< XEmbeddedScripts > xScripts( m_pData->rDocumentAccess.getEmbeddedDocumentScripts() );
414 Reference< XLibraryContainer > xContainer;
415 if ( xScripts.is() )
416 xContainer.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW );
418 if ( xContainer.is() )
420 // a library container exists; check if it's empty
422 // if there are libraries except the "Standard" library
423 // we assume that they are not empty (because they have been created by the user)
424 if ( !xContainer->hasElements() )
425 bHasMacroLib = sal_False;
426 else
428 ::rtl::OUString aStdLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
429 Sequence< ::rtl::OUString > aElements = xContainer->getElementNames();
430 if ( aElements.getLength() )
432 if ( aElements.getLength() > 1 || !aElements[0].equals( aStdLibName ) )
433 bHasMacroLib = sal_True;
434 else
436 // usually a "Standard" library is always present (design)
437 // for this reason we must check if it's empty
439 // Note: Since #i73229#, this is not true anymore. There's no default
440 // "Standard" lib anymore. Wouldn't it be time to get completely
441 // rid of the "Standard" thingie - this shouldn't be necessary
442 // anymore, should it?
443 // 2007-01-25 / frank.schoenheit@sun.com
444 Reference < XLibraryQueryExecutable > xLib( xContainer, UNO_QUERY );
445 if ( xLib.is() )
446 bHasMacroLib = xLib->HasExecutableCode( aStdLibName );
452 catch( const Exception& )
454 DBG_UNHANDLED_EXCEPTION();
457 return bHasMacroLib;
460 //--------------------------------------------------------------------
461 sal_Bool DocumentMacroMode::storageHasMacros( const Reference< XStorage >& _rxStorage )
463 sal_Bool bHasMacros = sal_False;
464 if ( _rxStorage.is() )
468 static const ::rtl::OUString s_sBasicStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ) );
469 static const ::rtl::OUString s_sScriptsStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ) );
471 bHasMacros =( ( _rxStorage->hasByName( s_sBasicStorageName )
472 && _rxStorage->isStorageElement( s_sBasicStorageName )
474 || ( _rxStorage->hasByName( s_sScriptsStorageName )
475 && _rxStorage->isStorageElement( s_sScriptsStorageName )
479 catch ( const Exception& )
481 DBG_UNHANDLED_EXCEPTION();
484 return bHasMacros;
487 //--------------------------------------------------------------------
488 sal_Bool DocumentMacroMode::checkMacrosOnLoading( const Reference< XInteractionHandler >& _rxInteraction )
490 sal_Bool bAllow = sal_False;
491 if ( SvtSecurityOptions().IsMacroDisabled() )
493 // no macro should be executed at all
494 bAllow = disallowMacroExecution();
496 else
498 if ( m_pData->rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() )
500 bAllow = adjustMacroMode( _rxInteraction );
502 else if ( !isMacroExecutionDisallowed() )
504 // if macros will be added by the user later, the security check is obsolete
505 bAllow = allowMacroExecution();
508 return bAllow;
511 //........................................................................
512 } // namespace sfx2
513 //........................................................................