Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / doc / docmacromode.cxx
blob3bcbf2de5309ea169053e3ce0e4e187bb4ceff32
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "sfx2/docmacromode.hxx"
31 #include "sfx2/signaturestate.hxx"
32 #include "sfx2/docfile.hxx"
34 /** === begin UNO includes === **/
35 #include <com/sun/star/document/MacroExecMode.hpp>
36 #include <com/sun/star/task/ErrorCodeRequest.hpp>
37 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
38 #include <com/sun/star/task/InteractionClassification.hpp>
39 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
40 #include <com/sun/star/script/XLibraryQueryExecutable.hpp>
41 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
42 /** === end UNO includes === **/
44 #include <comphelper/componentcontext.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <framework/interaction.hxx>
47 #include <osl/file.hxx>
48 #include <rtl/ref.hxx>
49 #include <unotools/securityoptions.hxx>
50 #include <svtools/sfxecode.hxx>
51 #include <tools/diagnose_ex.h>
52 #include <tools/urlobj.hxx>
54 //........................................................................
55 namespace sfx2
57 //........................................................................
59 /** === begin UNO using === **/
60 using ::com::sun::star::uno::Reference;
61 using ::com::sun::star::task::XInteractionHandler;
62 using ::com::sun::star::uno::Any;
63 using ::com::sun::star::task::XInteractionHandler;
64 using ::com::sun::star::uno::Sequence;
65 using ::com::sun::star::task::XInteractionContinuation;
66 using ::com::sun::star::task::XInteractionRequest;
67 using ::com::sun::star::task::DocumentMacroConfirmationRequest;
68 using ::com::sun::star::task::ErrorCodeRequest;
69 using ::com::sun::star::uno::Exception;
70 using ::com::sun::star::security::XDocumentDigitalSignatures;
71 using ::com::sun::star::security::DocumentSignatureInformation;
72 using ::com::sun::star::embed::XStorage;
73 using ::com::sun::star::task::InteractionClassification_QUERY;
74 using ::com::sun::star::document::XEmbeddedScripts;
75 using ::com::sun::star::uno::UNO_SET_THROW;
76 using ::com::sun::star::script::XLibraryContainer;
77 using ::com::sun::star::script::XLibraryQueryExecutable;
78 using ::com::sun::star::script::vba::XVBACompatibility;
79 using ::com::sun::star::container::XNameAccess;
80 using ::com::sun::star::uno::UNO_QUERY_THROW;
81 using ::com::sun::star::uno::UNO_QUERY;
82 /** === end UNO using === **/
83 namespace MacroExecMode = ::com::sun::star::document::MacroExecMode;
85 //====================================================================
86 //= DocumentMacroMode_Data
87 //====================================================================
88 struct DocumentMacroMode_Data
90 IMacroDocumentAccess& m_rDocumentAccess;
91 sal_Bool m_bMacroDisabledMessageShown;
92 sal_Bool m_bDocMacroDisabledMessageShown;
94 DocumentMacroMode_Data( IMacroDocumentAccess& rDocumentAccess )
95 :m_rDocumentAccess( rDocumentAccess )
96 ,m_bMacroDisabledMessageShown( sal_False )
97 ,m_bDocMacroDisabledMessageShown( sal_False )
102 //====================================================================
103 //= helper
104 //====================================================================
105 namespace
107 //................................................................
108 void lcl_showGeneralSfxErrorOnce( const Reference< XInteractionHandler >& rxHandler, const sal_Int32 nSfxErrorCode, sal_Bool& rbAlreadyShown )
110 if ( rbAlreadyShown )
111 return;
113 ErrorCodeRequest aErrorCodeRequest;
114 aErrorCodeRequest.ErrCode = nSfxErrorCode;
116 SfxMedium::CallApproveHandler( rxHandler, makeAny( aErrorCodeRequest ), sal_False );
117 rbAlreadyShown = sal_True;
120 //................................................................
121 void lcl_showMacrosDisabledError( const Reference< XInteractionHandler >& rxHandler, sal_Bool& rbAlreadyShown )
123 lcl_showGeneralSfxErrorOnce( rxHandler, ERRCODE_SFX_MACROS_SUPPORT_DISABLED, rbAlreadyShown );
126 //................................................................
127 void lcl_showDocumentMacrosDisabledError( const Reference< XInteractionHandler >& rxHandler, sal_Bool& rbAlreadyShown )
129 #ifdef MACOSX
130 lcl_showGeneralSfxErrorOnce( rxHandler, ERRCODE_SFX_DOCUMENT_MACRO_DISABLED_MAC, rbAlreadyShown );
131 #else
132 lcl_showGeneralSfxErrorOnce( rxHandler, ERRCODE_SFX_DOCUMENT_MACRO_DISABLED, rbAlreadyShown );
133 #endif
136 //................................................................
137 sal_Bool lcl_showMacroWarning( const Reference< XInteractionHandler >& rxHandler,
138 const ::rtl::OUString& rDocumentLocation )
140 DocumentMacroConfirmationRequest aRequest;
141 aRequest.DocumentURL = rDocumentLocation;
142 return SfxMedium::CallApproveHandler( rxHandler, makeAny( aRequest ), sal_True );
146 //====================================================================
147 //= DocumentMacroMode
148 //====================================================================
149 //--------------------------------------------------------------------
150 DocumentMacroMode::DocumentMacroMode( IMacroDocumentAccess& rDocumentAccess )
151 :m_pData( new DocumentMacroMode_Data( rDocumentAccess ) )
155 //--------------------------------------------------------------------
156 DocumentMacroMode::~DocumentMacroMode()
160 //--------------------------------------------------------------------
161 sal_Bool DocumentMacroMode::allowMacroExecution()
163 m_pData->m_rDocumentAccess.setCurrentMacroExecMode( MacroExecMode::ALWAYS_EXECUTE_NO_WARN );
164 return sal_True;
167 //--------------------------------------------------------------------
168 sal_Bool DocumentMacroMode::disallowMacroExecution()
170 m_pData->m_rDocumentAccess.setCurrentMacroExecMode( MacroExecMode::NEVER_EXECUTE );
171 return sal_False;
174 //--------------------------------------------------------------------
175 sal_Bool DocumentMacroMode::adjustMacroMode( const Reference< XInteractionHandler >& rxInteraction )
177 sal_uInt16 nMacroExecutionMode = m_pData->m_rDocumentAccess.getCurrentMacroExecMode();
179 if ( SvtSecurityOptions().IsMacroDisabled() )
181 // no macro should be executed at all
182 lcl_showMacrosDisabledError( rxInteraction, m_pData->m_bMacroDisabledMessageShown );
183 return disallowMacroExecution();
186 // get setting from configuration if required
187 enum AutoConfirmation
189 eNoAutoConfirm,
190 eAutoConfirmApprove,
191 eAutoConfirmReject
193 AutoConfirmation eAutoConfirm( eNoAutoConfirm );
195 if ( ( nMacroExecutionMode == MacroExecMode::USE_CONFIG )
196 || ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION )
197 || ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION )
200 SvtSecurityOptions aOpt;
201 switch ( aOpt.GetMacroSecurityLevel() )
203 case 3:
204 nMacroExecutionMode = MacroExecMode::FROM_LIST_NO_WARN;
205 break;
206 case 2:
207 nMacroExecutionMode = MacroExecMode::FROM_LIST_AND_SIGNED_WARN;
208 break;
209 case 1:
210 nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE;
211 break;
212 case 0:
213 nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
214 break;
215 default:
216 OSL_FAIL( "DocumentMacroMode::adjustMacroMode: unexpected macro security level!" );
217 nMacroExecutionMode = MacroExecMode::NEVER_EXECUTE;
220 if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION )
221 eAutoConfirm = eAutoConfirmReject;
222 else if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION )
223 eAutoConfirm = eAutoConfirmApprove;
226 if ( nMacroExecutionMode == MacroExecMode::NEVER_EXECUTE )
227 return sal_False;
229 if ( nMacroExecutionMode == MacroExecMode::ALWAYS_EXECUTE_NO_WARN )
230 return sal_True;
234 ::rtl::OUString sReferrer( m_pData->m_rDocumentAccess.getDocumentLocation() );
236 // get document location from medium name and check whether it is a trusted one
237 // the service is created ohne document version, since it is not of interest here
238 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
239 Reference< XDocumentDigitalSignatures > xSignatures;
240 if ( aContext.createComponent( "com.sun.star.security.DocumentDigitalSignatures", xSignatures ) )
242 INetURLObject aURLReferer( sReferrer );
244 ::rtl::OUString aLocation;
245 if ( aURLReferer.removeSegment() )
246 aLocation = aURLReferer.GetMainURL( INetURLObject::NO_DECODE );
248 if ( !aLocation.isEmpty() && xSignatures->isLocationTrusted( aLocation ) )
250 return allowMacroExecution();
254 // at this point it is clear that the document is not in the secure location
255 if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN )
257 lcl_showDocumentMacrosDisabledError( rxInteraction, m_pData->m_bDocMacroDisabledMessageShown );
258 return disallowMacroExecution();
261 // check whether the document is signed with trusted certificate
262 if ( nMacroExecutionMode != MacroExecMode::FROM_LIST )
264 // the trusted macro check will also retrieve the signature state ( small optimization )
265 sal_Bool bHasTrustedMacroSignature = m_pData->m_rDocumentAccess.hasTrustedScriptingSignature( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN );
267 sal_uInt16 nSignatureState = m_pData->m_rDocumentAccess.getScriptingSignatureState();
268 if ( nSignatureState == SIGNATURESTATE_SIGNATURES_BROKEN )
270 // the signature is broken, no macro execution
271 if ( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
272 m_pData->m_rDocumentAccess.showBrokenSignatureWarning( rxInteraction );
274 return disallowMacroExecution();
276 else if ( bHasTrustedMacroSignature )
278 // there is trusted macro signature, allow macro execution
279 return allowMacroExecution();
281 else if ( nSignatureState == SIGNATURESTATE_SIGNATURES_OK
282 || nSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED )
284 // there is valid signature, but it is not from the trusted author
285 return disallowMacroExecution();
289 // at this point it is clear that the document is neither in secure location nor signed with trusted certificate
290 if ( ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
291 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
294 if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
295 lcl_showDocumentMacrosDisabledError( rxInteraction, m_pData->m_bDocMacroDisabledMessageShown );
297 return disallowMacroExecution();
300 catch ( const Exception& )
302 if ( ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN )
303 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
304 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
307 return disallowMacroExecution();
311 // conformation is required
312 sal_Bool bSecure = sal_False;
314 if ( eAutoConfirm == eNoAutoConfirm )
316 ::rtl::OUString sReferrer( m_pData->m_rDocumentAccess.getDocumentLocation() );
318 ::rtl::OUString aSystemFileURL;
319 if ( osl::FileBase::getSystemPathFromFileURL( sReferrer, aSystemFileURL ) == osl::FileBase::E_None )
320 sReferrer = aSystemFileURL;
322 bSecure = lcl_showMacroWarning( rxInteraction, sReferrer );
324 else
325 bSecure = ( eAutoConfirm == eAutoConfirmApprove );
327 return ( bSecure ? allowMacroExecution() : disallowMacroExecution() );
330 //--------------------------------------------------------------------
331 sal_Bool DocumentMacroMode::isMacroExecutionDisallowed() const
333 return m_pData->m_rDocumentAccess.getCurrentMacroExecMode() == MacroExecMode::NEVER_EXECUTE;
336 //--------------------------------------------------------------------
337 sal_Bool DocumentMacroMode::hasMacroLibrary() const
339 sal_Bool bHasMacroLib = sal_False;
340 #ifndef DISABLE_SCRIPTING
343 Reference< XEmbeddedScripts > xScripts( m_pData->m_rDocumentAccess.getEmbeddedDocumentScripts() );
344 Reference< XLibraryContainer > xContainer;
345 if ( xScripts.is() )
346 xContainer.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW );
348 Reference< XVBACompatibility > xDocVBAMode( xContainer, UNO_QUERY );
349 sal_Bool bIsVBAMode = ( xDocVBAMode.is() && xDocVBAMode->getVBACompatibilityMode() );
350 if ( xContainer.is() )
352 // a library container exists; check if it's empty
354 // if there are libraries except the "Standard" library
355 // we assume that they are not empty (because they have been created by the user)
356 if ( !xContainer->hasElements() )
357 bHasMacroLib = sal_False;
358 else
360 ::rtl::OUString aStdLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
361 Sequence< ::rtl::OUString > aElements = xContainer->getElementNames();
362 sal_Int32 nElementCount = aElements.getLength();
363 if ( nElementCount )
365 // old check, if more than 1 library or the first library isn't the expected 'Standard'
366 // trigger the security 'nag' dialog
367 if ( !bIsVBAMode && ( nElementCount > 1 || !aElements[0].equals( aStdLibName ) ) )
368 bHasMacroLib = sal_True;
369 else
371 // other wise just check all libraries for executeable code
372 Reference< XLibraryQueryExecutable > xLib( xContainer, UNO_QUERY );
373 if ( xLib.is() )
375 const ::rtl::OUString* pElementName = aElements.getConstArray();
376 for ( sal_Int32 index = 0; index < nElementCount; ++index )
378 bHasMacroLib = xLib->HasExecutableCode( pElementName[index] );
379 if ( bHasMacroLib )
380 break;
387 if ( bIsVBAMode && !bHasMacroLib && xScripts.is() )
389 Reference< XLibraryContainer > xDlgContainer( xScripts->getDialogLibraries(), UNO_QUERY );
390 if ( xDlgContainer.is() && xDlgContainer->hasElements() )
392 Sequence< ::rtl::OUString > aElements = xDlgContainer->getElementNames();
393 sal_Int32 nElementCount = aElements.getLength();
394 const ::rtl::OUString* pElementName = aElements.getConstArray();
395 for ( sal_Int32 index = 0; index < nElementCount; ++index )
397 Reference< XNameAccess > xNameAccess;
398 xDlgContainer->getByName( pElementName[index] ) >>= xNameAccess;
399 if ( xNameAccess.is() && xNameAccess->hasElements() )
401 bHasMacroLib = sal_True;
402 break;
408 catch( const Exception& )
410 DBG_UNHANDLED_EXCEPTION();
412 #endif
413 return bHasMacroLib;
416 //--------------------------------------------------------------------
417 sal_Bool DocumentMacroMode::storageHasMacros( const Reference< XStorage >& rxStorage )
419 sal_Bool bHasMacros = sal_False;
420 if ( rxStorage.is() )
424 static const ::rtl::OUString s_sBasicStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ) );
425 static const ::rtl::OUString s_sScriptsStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ) );
427 bHasMacros =( ( rxStorage->hasByName( s_sBasicStorageName )
428 && rxStorage->isStorageElement( s_sBasicStorageName )
430 || ( rxStorage->hasByName( s_sScriptsStorageName )
431 && rxStorage->isStorageElement( s_sScriptsStorageName )
435 catch ( const Exception& )
437 DBG_UNHANDLED_EXCEPTION();
440 return bHasMacros;
443 //--------------------------------------------------------------------
444 sal_Bool DocumentMacroMode::checkMacrosOnLoading( const Reference< XInteractionHandler >& rxInteraction )
446 sal_Bool bAllow = sal_False;
447 if ( SvtSecurityOptions().IsMacroDisabled() )
449 // no macro should be executed at all
450 bAllow = disallowMacroExecution();
452 else
454 if ( m_pData->m_rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() )
456 bAllow = adjustMacroMode( rxInteraction );
458 else if ( !isMacroExecutionDisallowed() )
460 // if macros will be added by the user later, the security check is obsolete
461 bAllow = allowMacroExecution();
464 return bAllow;
467 //........................................................................
468 } // namespace sfx2
469 //........................................................................
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */