tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / dbaccess / source / core / dataaccess / ModelImpl.cxx
blob9970f97ddf83ffaaa860b79ea272db1c30e116be
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <databasecontext.hxx>
21 #include "databasedocument.hxx"
22 #include "datasource.hxx"
23 #include <definitioncontainer.hxx>
24 #include <ModelImpl.hxx>
25 #include <sdbcoretools.hxx>
27 #include <com/sun/star/beans/PropertyBag.hpp>
28 #include <com/sun/star/container/XSet.hpp>
29 #include <com/sun/star/document/MacroExecMode.hpp>
30 #include <com/sun/star/embed/XTransactedObject.hpp>
31 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
32 #include <com/sun/star/embed/StorageFactory.hpp>
33 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
34 #include <com/sun/star/io/IOException.hpp>
35 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
37 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
38 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
39 #include <com/sun/star/util/NumberFormatsSupplier.hpp>
40 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
41 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
42 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
44 #include <cppuhelper/exc_hlp.hxx>
45 #include <cppuhelper/implbase.hxx>
46 #include <comphelper/storagehelper.hxx>
47 #include <comphelper/types.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <sfx2/docfile.hxx>
50 #include <sfx2/signaturestate.hxx>
51 #include <comphelper/diagnose_ex.hxx>
52 #include <osl/file.hxx>
53 #include <osl/diagnose.h>
54 #include <sal/log.hxx>
55 #include <tools/urlobj.hxx>
56 #include <unotools/configmgr.hxx>
57 #include <unotools/tempfile.hxx>
58 #include <i18nlangtag/languagetag.hxx>
60 #include <algorithm>
61 #include <utility>
63 using namespace css;
64 using namespace ::com::sun::star::document;
65 using namespace ::com::sun::star::sdbc;
66 using namespace ::com::sun::star::sdb;
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::lang;
70 using namespace ::com::sun::star::embed;
71 using namespace ::com::sun::star::container;
72 using namespace ::com::sun::star::util;
73 using namespace ::com::sun::star::io;
74 using namespace ::com::sun::star::frame;
75 using namespace ::com::sun::star::task;
76 using namespace ::com::sun::star::script;
77 using namespace ::cppu;
78 using namespace ::osl;
79 using namespace ::comphelper;
81 namespace dbaccess
84 // DocumentStorageAccess
85 class DocumentStorageAccess : public ::cppu::WeakImplHelper< XDocumentSubStorageSupplier
86 , XTransactionListener >
88 typedef std::map< OUString, Reference< XStorage > > NamedStorages;
90 ::osl::Mutex m_aMutex;
91 /// all sub storages which we ever gave to the outer world
92 NamedStorages m_aExposedStorages;
93 ODatabaseModelImpl* m_pModelImplementation;
94 bool m_bPropagateCommitToRoot;
95 bool m_bDisposingSubStorages;
97 public:
98 explicit DocumentStorageAccess( ODatabaseModelImpl& _rModelImplementation )
99 :m_pModelImplementation( &_rModelImplementation )
100 ,m_bPropagateCommitToRoot( true )
101 ,m_bDisposingSubStorages( false )
105 protected:
106 virtual ~DocumentStorageAccess() override
110 public:
111 void dispose();
113 // XDocumentSubStorageSupplier
114 virtual Reference< XStorage > SAL_CALL getDocumentSubStorage( const OUString& aStorageName, ::sal_Int32 _nMode ) override;
115 virtual Sequence< OUString > SAL_CALL getDocumentSubStoragesNames( ) override;
117 // XTransactionListener
118 virtual void SAL_CALL preCommit( const css::lang::EventObject& aEvent ) override;
119 virtual void SAL_CALL commited( const css::lang::EventObject& aEvent ) override;
120 virtual void SAL_CALL preRevert( const css::lang::EventObject& aEvent ) override;
121 virtual void SAL_CALL reverted( const css::lang::EventObject& aEvent ) override;
123 // XEventListener
124 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
126 /// disposes all storages managed by this instance
127 void disposeStorages();
129 /// disposes all known sub storages
130 void commitStorages();
132 /// commits the dedicated "database" storage
133 bool commitEmbeddedStorage( bool _bPreventRootCommits );
135 private:
136 /** opens the sub storage with the given name, in the given mode
138 Reference< XStorage > impl_openSubStorage_nothrow( const OUString& _rStorageName, sal_Int32 _nMode );
140 void impl_suspendCommitPropagation()
142 OSL_ENSURE( m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_suspendCommitPropagation: already suspended" );
143 m_bPropagateCommitToRoot = false;
145 void impl_resumeCommitPropagation()
147 OSL_ENSURE( !m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_resumeCommitPropagation: not suspended" );
148 m_bPropagateCommitToRoot = true;
153 void DocumentStorageAccess::dispose()
155 ::osl::MutexGuard aGuard( m_aMutex );
157 for (auto const& exposedStorage : m_aExposedStorages)
161 Reference< XTransactionBroadcaster > xBroadcaster(exposedStorage.second, UNO_QUERY);
162 if ( xBroadcaster.is() )
163 xBroadcaster->removeTransactionListener( this );
165 catch( const Exception& )
167 DBG_UNHANDLED_EXCEPTION("dbaccess");
171 m_aExposedStorages.clear();
173 m_pModelImplementation = nullptr;
176 Reference< XStorage > DocumentStorageAccess::impl_openSubStorage_nothrow( const OUString& _rStorageName, sal_Int32 _nDesiredMode )
178 OSL_ENSURE( !_rStorageName.isEmpty(),"ODatabaseModelImpl::impl_openSubStorage_nothrow: Invalid storage name!" );
180 Reference< XStorage > xStorage;
183 Reference< XStorage > xRootStorage( m_pModelImplementation->getOrCreateRootStorage() );
184 if ( xRootStorage.is() )
186 sal_Int32 nRealMode = m_pModelImplementation->m_bDocumentReadOnly ? ElementModes::READ : _nDesiredMode;
187 if ( nRealMode == ElementModes::READ )
189 if ( xRootStorage.is() && !xRootStorage->hasByName( _rStorageName ) )
190 return xStorage;
193 xStorage = xRootStorage->openStorageElement( _rStorageName, nRealMode );
195 Reference< XTransactionBroadcaster > xBroad( xStorage, UNO_QUERY );
196 if ( xBroad.is() )
197 xBroad->addTransactionListener( this );
200 catch( const Exception& )
202 DBG_UNHANDLED_EXCEPTION("dbaccess");
205 return xStorage;
208 void DocumentStorageAccess::disposeStorages()
210 m_bDisposingSubStorages = true;
212 for (auto & exposedStorage : m_aExposedStorages)
216 ::comphelper::disposeComponent( exposedStorage.second );
218 catch( const Exception& )
220 DBG_UNHANDLED_EXCEPTION("dbaccess");
223 m_aExposedStorages.clear();
225 m_bDisposingSubStorages = false;
228 void DocumentStorageAccess::commitStorages()
232 for (auto const& exposedStorage : m_aExposedStorages)
234 tools::stor::commitStorageIfWriteable( exposedStorage.second );
237 catch(const WrappedTargetException&)
239 // WrappedTargetException not allowed to leave
240 throw IOException();
244 bool DocumentStorageAccess::commitEmbeddedStorage( bool _bPreventRootCommits )
246 if ( _bPreventRootCommits )
247 impl_suspendCommitPropagation();
249 bool bSuccess = false;
252 NamedStorages::const_iterator pos = m_aExposedStorages.find( u"database"_ustr );
253 if ( pos != m_aExposedStorages.end() )
254 bSuccess = tools::stor::commitStorageIfWriteable( pos->second );
256 catch( Exception& )
258 DBG_UNHANDLED_EXCEPTION("dbaccess");
261 if ( _bPreventRootCommits )
262 impl_resumeCommitPropagation();
264 return bSuccess;
268 Reference< XStorage > SAL_CALL DocumentStorageAccess::getDocumentSubStorage( const OUString& aStorageName, ::sal_Int32 _nDesiredMode )
270 ::osl::MutexGuard aGuard( m_aMutex );
271 NamedStorages::const_iterator pos = m_aExposedStorages.find( aStorageName );
272 if ( pos == m_aExposedStorages.end() )
274 Reference< XStorage > xResult = impl_openSubStorage_nothrow( aStorageName, _nDesiredMode );
275 pos = m_aExposedStorages.emplace( aStorageName, xResult ).first;
278 return pos->second;
281 Sequence< OUString > SAL_CALL DocumentStorageAccess::getDocumentSubStoragesNames( )
283 Reference< XStorage > xRootStor( m_pModelImplementation->getRootStorage() );
284 if ( !xRootStor.is() )
285 return Sequence< OUString >();
287 std::vector< OUString > aNames;
289 const Sequence< OUString > aElementNames( xRootStor->getElementNames() );
290 for ( OUString const & name : aElementNames )
292 if ( xRootStor->isStorageElement( name ) )
293 aNames.push_back( name );
295 return aNames.empty()
296 ? Sequence< OUString >()
297 : Sequence< OUString >( aNames.data(), aNames.size() );
300 void SAL_CALL DocumentStorageAccess::preCommit( const css::lang::EventObject& /*aEvent*/ )
302 // not interested in
305 void SAL_CALL DocumentStorageAccess::commited( const css::lang::EventObject& aEvent )
307 ::osl::MutexGuard aGuard( m_aMutex );
309 if ( m_pModelImplementation )
310 m_pModelImplementation->setModified( true );
312 if ( !(m_pModelImplementation && m_bPropagateCommitToRoot) )
313 return;
315 Reference< XStorage > xStorage( aEvent.Source, UNO_QUERY );
317 // check if this is the dedicated "database" sub storage
318 NamedStorages::const_iterator pos = m_aExposedStorages.find( u"database"_ustr );
319 if ( ( pos != m_aExposedStorages.end() )
320 && ( pos->second == xStorage )
323 // if so, also commit the root storage
324 m_pModelImplementation->commitRootStorage();
328 void SAL_CALL DocumentStorageAccess::preRevert( const css::lang::EventObject& /*aEvent*/ )
330 // not interested in
333 void SAL_CALL DocumentStorageAccess::reverted( const css::lang::EventObject& /*aEvent*/ )
335 // not interested in
338 void SAL_CALL DocumentStorageAccess::disposing( const css::lang::EventObject& Source )
340 OSL_ENSURE( Reference< XStorage >( Source.Source, UNO_QUERY ).is(), "DocumentStorageAccess::disposing: No storage? What's this?" );
342 if ( m_bDisposingSubStorages )
343 return;
345 auto find = std::find_if(m_aExposedStorages.begin(), m_aExposedStorages.end(),
346 [&Source](const NamedStorages::value_type& rEntry) { return rEntry.second == Source.Source; });
347 if (find != m_aExposedStorages.end())
348 m_aExposedStorages.erase( find );
351 // ODatabaseModelImpl
353 ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XComponentContext >& _rxContext, ODatabaseContext& _rDBContext )
354 :m_aContainer()
355 ,m_aMacroMode( *this )
356 ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE )
357 ,m_rDBContext( _rDBContext )
358 ,m_refCount(0)
359 ,m_bModificationLock( false )
360 ,m_bDocumentInitialized( false )
361 ,m_nScriptingSignatureState(SignatureState::UNKNOWN)
362 ,m_aContext( _rxContext )
363 ,m_nLoginTimeout(0)
364 ,m_bReadOnly(false)
365 ,m_bPasswordRequired(false)
366 ,m_bSuppressVersionColumns(true)
367 ,m_bModified(false)
368 ,m_bDocumentReadOnly(false)
369 ,m_bMacroCallsSeenWhileLoading(false)
370 ,m_nControllerLockCount(0)
372 // some kind of default
373 m_sConnectURL = "jdbc:";
374 m_aTableFilter = { u"%"_ustr };
375 impl_construct_nothrow();
378 ODatabaseModelImpl::ODatabaseModelImpl(
379 OUString _sRegistrationName,
380 const Reference< XComponentContext >& _rxContext,
381 ODatabaseContext& _rDBContext
383 :m_aContainer()
384 ,m_aMacroMode( *this )
385 ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE )
386 ,m_rDBContext( _rDBContext )
387 ,m_refCount(0)
388 ,m_bModificationLock( false )
389 ,m_bDocumentInitialized( false )
390 ,m_nScriptingSignatureState(SignatureState::UNKNOWN)
391 ,m_aContext( _rxContext )
392 ,m_sName(std::move(_sRegistrationName))
393 ,m_nLoginTimeout(0)
394 ,m_bReadOnly(false)
395 ,m_bPasswordRequired(false)
396 ,m_bSuppressVersionColumns(true)
397 ,m_bModified(false)
398 ,m_bDocumentReadOnly(false)
399 ,m_bMacroCallsSeenWhileLoading(false)
400 ,m_nControllerLockCount(0)
402 impl_construct_nothrow();
405 ODatabaseModelImpl::~ODatabaseModelImpl()
409 void ODatabaseModelImpl::impl_construct_nothrow()
411 // create the property bag to hold the settings (also known as "Info" property)
414 // the set of property value types in the bag is limited:
415 Sequence< Type > aAllowedTypes({
416 cppu::UnoType<sal_Bool>::get(),
417 cppu::UnoType<double>::get(),
418 cppu::UnoType<OUString>::get(),
419 cppu::UnoType<sal_Int32>::get(),
420 cppu::UnoType<sal_Int16>::get(),
421 cppu::UnoType<Sequence< Any >>::get(),
424 m_xSettings = PropertyBag::createWithTypes( m_aContext, aAllowedTypes, false/*AllowEmptyPropertyName*/, true/*AutomaticAddition*/ );
426 // insert the default settings
427 Reference< XPropertyContainer > xContainer( m_xSettings, UNO_QUERY_THROW );
428 Reference< XSet > xSettingsSet( m_xSettings, UNO_QUERY_THROW );
429 for (auto& setting : getDefaultDataSourceSettings())
431 if (!setting.DefaultValue.hasValue())
433 Property aProperty(setting.Name,
435 setting.ValueType,
436 PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID
438 xSettingsSet->insert( Any( aProperty ) );
440 else
442 xContainer->addProperty(setting.Name,
443 PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT,
444 setting.DefaultValue
449 catch( const Exception& )
451 DBG_UNHANDLED_EXCEPTION("dbaccess");
453 m_rDBContext.appendAtTerminateListener(*this);
456 namespace
458 OUString lcl_getContainerStorageName_throw( ODatabaseModelImpl::ObjectType _eType )
460 OUString sName;
461 switch ( _eType )
463 case ODatabaseModelImpl::ObjectType::Form: sName = u"forms"_ustr; break;
464 case ODatabaseModelImpl::ObjectType::Report: sName = u"reports"_ustr; break;
465 case ODatabaseModelImpl::ObjectType::Query: sName = u"queries"_ustr; break;
466 case ODatabaseModelImpl::ObjectType::Table: sName = u"tables"_ustr; break;
467 default:
468 throw RuntimeException();
470 return sName;
473 bool lcl_hasObjectWithMacros_throw( const ODefinitionContainer_Impl& _rObjectDefinitions, const Reference< XStorage >& _rxContainerStorage )
475 bool bSomeDocHasMacros = false;
477 for (auto const& objectDefinition : _rObjectDefinitions)
479 const TContentPtr& rDefinition( objectDefinition.second );
480 const OUString& rPersistentName( rDefinition->m_aProps.sPersistentName );
482 if ( rPersistentName.isEmpty() )
483 { // it's a logical sub folder used to organize the real objects
484 const ODefinitionContainer_Impl& rSubFoldersObjectDefinitions( dynamic_cast< const ODefinitionContainer_Impl& >( *rDefinition ) );
485 bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rSubFoldersObjectDefinitions, _rxContainerStorage );
486 if (bSomeDocHasMacros)
487 break;
488 continue;
491 bSomeDocHasMacros = ODatabaseModelImpl::objectHasMacros( _rxContainerStorage, rPersistentName );
492 if (bSomeDocHasMacros)
493 break;
495 return bSomeDocHasMacros;
498 bool lcl_hasObjectsWithMacros_nothrow( ODatabaseModelImpl& _rModel, const ODatabaseModelImpl::ObjectType _eType )
500 bool bSomeDocHasMacros = false;
502 const OContentHelper_Impl& rContainerData( *_rModel.getObjectContainer( _eType ) );
503 const ODefinitionContainer_Impl& rObjectDefinitions = dynamic_cast< const ODefinitionContainer_Impl& >( rContainerData );
507 Reference< XStorage > xContainerStorage( _rModel.getStorage( _eType ) );
508 // note the READWRITE here: If the storage already existed before, then the OpenMode will
509 // be ignored, anyway.
510 // If the storage did not yet exist, then it will be created. If the database document
511 // is read-only, the OpenMode will be automatically downgraded to READ. Otherwise,
512 // the storage will in fact be created as READWRITE. While this is not strictly necessary
513 // for this particular use case here, it is required since the storage is *cached*, and
514 // later use cases will need the READWRITE mode.
516 if ( xContainerStorage.is() )
517 bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rObjectDefinitions, xContainerStorage );
519 catch( const Exception& )
521 DBG_UNHANDLED_EXCEPTION("dbaccess");
522 // be on the safe side: If we can't reliably determine whether there are macros,
523 // assume there actually are. Better this way, than the other way round.
524 bSomeDocHasMacros = true;
527 return bSomeDocHasMacros;
531 bool ODatabaseModelImpl::objectHasMacros( const Reference< XStorage >& _rxContainerStorage, const OUString& _rPersistentName )
533 OSL_PRECOND( _rxContainerStorage.is(), "ODatabaseModelImpl::objectHasMacros: this will crash!" );
535 bool bHasMacros = true;
538 if ( !_rxContainerStorage->hasByName( _rPersistentName ) )
539 return false;
541 Reference< XStorage > xObjectStor( _rxContainerStorage->openStorageElement(
542 _rPersistentName, ElementModes::READ ) );
544 bHasMacros = ::sfx2::DocumentMacroMode::storageHasMacros( xObjectStor );
546 catch( const Exception& )
548 DBG_UNHANDLED_EXCEPTION("dbaccess");
550 return bHasMacros;
553 void ODatabaseModelImpl::reset()
555 m_bReadOnly = false;
556 for (auto & i : m_aContainer)
557 i.reset();
559 if ( m_pStorageAccess.is() )
561 m_pStorageAccess->dispose();
562 m_pStorageAccess.clear();
566 void ODatabaseModelImpl::disposing( const css::lang::EventObject& Source )
568 Reference<XConnection> xCon(Source.Source,UNO_QUERY);
569 if ( xCon.is() )
571 bool bStore = false;
572 for (OWeakConnectionArray::iterator i = m_aConnections.begin(); i != m_aConnections.end(); )
574 css::uno::Reference< css::sdbc::XConnection > xIterConn ( *i );
575 if ( !xIterConn.is())
577 i = m_aConnections.erase(i);
579 else if ( xCon == xIterConn )
581 *i = css::uno::WeakReference< css::sdbc::XConnection >();
582 bStore = true;
583 break;
584 } else
585 ++i;
588 if ( bStore )
589 commitRootStorage();
591 else
593 OSL_FAIL( "ODatabaseModelImpl::disposing: where does this come from?" );
597 void ODatabaseModelImpl::clearConnections()
599 OWeakConnectionArray aConnections;
600 aConnections.swap( m_aConnections );
602 Reference< XConnection > xConn;
603 for (auto const& connection : aConnections)
605 xConn = connection;
606 if ( xConn.is() )
610 xConn->close();
612 catch(const Exception&)
614 DBG_UNHANDLED_EXCEPTION("dbaccess");
619 m_xSharedConnectionManager = nullptr;
622 void ODatabaseModelImpl::dispose()
624 // dispose the data source and the model
627 rtl::Reference< ODatabaseSource > xDS( m_xDataSource );
628 if (xDS)
630 xDS->dispose();
631 m_xDataSource.clear();
634 rtl::Reference< ODatabaseDocument > xModel( m_xModel );
635 if (xModel)
637 xModel->dispose();
638 m_xModel.clear();
641 catch( const Exception& )
643 DBG_UNHANDLED_EXCEPTION("dbaccess");
645 m_xDataSource.clear();
646 m_xModel.clear();
648 for (auto const& elem : m_aContainer)
650 if ( elem )
651 elem->m_pDataSource = nullptr;
653 for (auto & i : m_aContainer)
654 i.reset();
656 clearConnections();
658 m_xNumberFormatsSupplier = nullptr;
662 bool bCouldStore = commitEmbeddedStorage( true );
663 // "true" means that committing the embedded storage should not trigger committing the root
664 // storage. This is because we are going to commit the root storage ourself, anyway
665 disposeStorages();
666 if ( bCouldStore )
667 commitRootStorage();
669 impl_switchToStorage_throw( nullptr );
671 catch( const Exception& )
673 DBG_UNHANDLED_EXCEPTION("dbaccess");
676 if ( m_pStorageAccess.is() )
678 m_pStorageAccess->dispose();
679 m_pStorageAccess.clear();
683 const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormatsSupplier()
685 if (!m_xNumberFormatsSupplier.is())
687 // the arguments : the work locale of the current user
688 Locale aLocale( LanguageTag::convertToLocale( utl::ConfigManager::getWorkLocale(), false));
690 m_xNumberFormatsSupplier.set( NumberFormatsSupplier::createWithLocale( m_aContext, aLocale ) );
692 return m_xNumberFormatsSupplier;
695 void ODatabaseModelImpl::setDocFileLocation( const OUString& i_rLoadedFrom )
697 ENSURE_OR_THROW( !i_rLoadedFrom.isEmpty(), "invalid URL" );
698 m_sDocFileLocation = i_rLoadedFrom;
701 void ODatabaseModelImpl::setResource( const OUString& i_rDocumentURL, const Sequence< PropertyValue >& _rArgs )
703 ENSURE_OR_THROW( !i_rDocumentURL.isEmpty(), "invalid URL" );
705 ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs );
706 #if OSL_DEBUG_LEVEL > 0
707 if ( aMediaDescriptor.has( u"SalvagedFile"_ustr ) )
709 OUString sSalvagedFile( aMediaDescriptor.getOrDefault( u"SalvagedFile"_ustr, OUString() ) );
710 // If SalvagedFile is an empty string, this indicates "the document is being recovered, but i_rDocumentURL already
711 // is the real document URL, not the temporary document location"
712 if ( sSalvagedFile.isEmpty() )
713 sSalvagedFile = i_rDocumentURL;
715 OSL_ENSURE( sSalvagedFile == i_rDocumentURL, "ODatabaseModelImpl::setResource: inconsistency!" );
716 // nowadays, setResource should only be called with the logical URL of the document
718 #endif
720 m_aMediaDescriptor = stripLoadArguments( aMediaDescriptor );
722 impl_switchToLogicalURL( i_rDocumentURL );
725 ::comphelper::NamedValueCollection ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments )
727 OSL_ENSURE( !_rArguments.has( u"Model"_ustr ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (1)!" );
728 OSL_ENSURE( !_rArguments.has( u"ViewName"_ustr ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (2)!" );
730 ::comphelper::NamedValueCollection aMutableArgs( _rArguments );
731 aMutableArgs.remove( u"Model"_ustr );
732 aMutableArgs.remove( u"ViewName"_ustr );
733 return aMutableArgs;
736 void ODatabaseModelImpl::disposeStorages()
738 getDocumentStorageAccess()->disposeStorages();
741 Reference< XSingleServiceFactory > ODatabaseModelImpl::createStorageFactory() const
743 return StorageFactory::create( m_aContext );
746 void ODatabaseModelImpl::commitRootStorage()
748 Reference< XStorage > xStorage( getOrCreateRootStorage() );
749 bool bSuccess = commitStorageIfWriteable_ignoreErrors( xStorage );
750 SAL_WARN_IF(!bSuccess && xStorage.is(), "dbaccess",
751 "ODatabaseModelImpl::commitRootStorage: could not commit the storage!");
754 Reference< XStorage > const & ODatabaseModelImpl::getOrCreateRootStorage()
756 if ( !m_xDocumentStorage.is() )
758 Reference< XSingleServiceFactory> xStorageFactory = StorageFactory::create( m_aContext );
759 Any aSource = m_aMediaDescriptor.get( u"Stream"_ustr );
760 if ( !aSource.hasValue() )
761 aSource = m_aMediaDescriptor.get( u"InputStream"_ustr );
762 if ( !aSource.hasValue() && !m_sDocFileLocation.isEmpty() )
763 aSource <<= m_sDocFileLocation;
764 // TODO: shouldn't we also check URL?
766 OSL_ENSURE( aSource.hasValue(), "ODatabaseModelImpl::getOrCreateRootStorage: no source to create the storage from!" );
768 if ( aSource.hasValue() )
770 Sequence< Any > aStorageCreationArgs{ aSource, Any(ElementModes::READWRITE) };
772 Reference< XStorage > xDocumentStorage;
773 OUString sURL;
774 aSource >>= sURL;
775 // Don't try to load a meta-URL as-is.
776 if (!sURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
780 xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW );
782 catch( const Exception& )
784 m_bDocumentReadOnly = true;
785 aStorageCreationArgs.getArray()[1] <<= ElementModes::READ;
788 xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW );
790 catch( const Exception& )
792 DBG_UNHANDLED_EXCEPTION("dbaccess");
797 impl_switchToStorage_throw( xDocumentStorage );
800 return m_xDocumentStorage.getTyped();
803 DocumentStorageAccess* ODatabaseModelImpl::getDocumentStorageAccess()
805 if ( !m_pStorageAccess.is() )
807 m_pStorageAccess = new DocumentStorageAccess( *this );
809 return m_pStorageAccess.get();
812 void ODatabaseModelImpl::modelIsDisposing( const bool _wasInitialized, ResetModelAccess )
814 m_xModel.clear();
816 // Basic libraries and Dialog libraries are a model facet, though held at this impl class.
817 // They automatically dispose themself when the model they belong to is being disposed.
818 // So, to not be tempted to do anything with them, again, we reset them.
819 m_xBasicLibraries.clear();
820 m_xDialogLibraries.clear();
822 m_bDocumentInitialized = _wasInitialized;
825 Reference< XDocumentSubStorageSupplier > ODatabaseModelImpl::getDocumentSubStorageSupplier()
827 return getDocumentStorageAccess();
830 bool ODatabaseModelImpl::commitEmbeddedStorage( bool _bPreventRootCommits )
832 return getDocumentStorageAccess()->commitEmbeddedStorage( _bPreventRootCommits );
835 bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< XStorage >& _rxStorage )
837 bool bTryToPreserveScriptSignature = false;
838 utl::TempFileNamed aTempFile;
839 aTempFile.EnableKillingFile();
840 OUString sTmpFileUrl = aTempFile.GetURL();
841 SignatureState aSignatureState = getScriptingSignatureState();
842 OUString sLocation = getDocFileLocation();
843 bool bIsEmbedded = sLocation.startsWith("vnd.sun.star.pkg:") && sLocation.endsWith("/EmbeddedDatabase");
844 if (!bIsEmbedded && !sLocation.isEmpty()
845 && (aSignatureState == SignatureState::OK || aSignatureState == SignatureState::NOTVALIDATED
846 || aSignatureState == SignatureState::INVALID
847 || aSignatureState == SignatureState::UNKNOWN))
849 bTryToPreserveScriptSignature = true;
850 // We need to first save the file (which removes the macro signature), then add the macro signature again.
851 // For that, we need a temporary copy of the original file.
852 osl::File::RC rc = osl::File::copy(sLocation, sTmpFileUrl);
853 if (rc != osl::FileBase::E_None)
854 throw uno::RuntimeException(u"Could not create temp file"_ustr);
857 bool bSuccess = false;
860 bSuccess = tools::stor::commitStorageIfWriteable( _rxStorage );
862 catch( const Exception& )
864 DBG_UNHANDLED_EXCEPTION("dbaccess");
867 // Preserve script signature if the script has not changed
868 if (bTryToPreserveScriptSignature)
870 OUString aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(_rxStorage));
871 uno::Reference<security::XDocumentDigitalSignatures> xDDSigns;
874 xDDSigns = security::DocumentDigitalSignatures::createWithVersion(
875 comphelper::getProcessComponentContext(), aODFVersion);
877 const OUString aScriptSignName
878 = xDDSigns->getScriptingContentSignatureDefaultStreamName();
880 if (!aScriptSignName.isEmpty())
882 Reference<XStorage> xReadOrig
883 = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
884 ZIP_STORAGE_FORMAT_STRING, sTmpFileUrl, ElementModes::READ);
885 if (!xReadOrig.is())
886 throw uno::RuntimeException("Could not read " + sTmpFileUrl);
887 uno::Reference<embed::XStorage> xMetaInf
888 = xReadOrig->openStorageElement(u"META-INF"_ustr, embed::ElementModes::READ);
890 uno::Reference<embed::XStorage> xTargetMetaInf
891 = _rxStorage->openStorageElement(u"META-INF"_ustr, embed::ElementModes::READWRITE);
892 if (xMetaInf.is() && xTargetMetaInf.is() && xMetaInf->hasByName(aScriptSignName))
894 xMetaInf->copyElementTo(aScriptSignName, xTargetMetaInf, aScriptSignName);
896 uno::Reference<embed::XTransactedObject> xTransact(xTargetMetaInf,
897 uno::UNO_QUERY);
898 if (xTransact.is())
899 xTransact->commit();
901 xTargetMetaInf->dispose();
903 // now check the copied signature
904 uno::Sequence<security::DocumentSignatureInformation> aInfos
905 = xDDSigns->verifyScriptingContentSignatures(
906 _rxStorage, uno::Reference<io::XInputStream>());
907 SignatureState nState = DocumentSignatures::getSignatureState(aInfos);
908 if (nState == SignatureState::OK || nState == SignatureState::NOTVALIDATED
909 || nState == SignatureState::PARTIAL_OK)
911 // commit the ZipStorage from target medium
912 xTransact.set(_rxStorage, uno::UNO_QUERY);
913 if (xTransact.is())
914 xTransact->commit();
916 else
918 SAL_WARN("dbaccess", "An invalid signature was copied!");
923 catch (uno::Exception&)
925 TOOLS_WARN_EXCEPTION("dbaccess", "");
929 return bSuccess;
932 void ODatabaseModelImpl::setModified( bool _bModified )
934 if ( isModifyLocked() )
935 return;
939 rtl::Reference< ODatabaseDocument > xModi( m_xModel );
940 if ( xModi.is() )
941 xModi->setModified( _bModified );
942 else
943 m_bModified = _bModified;
945 catch( const Exception& )
947 DBG_UNHANDLED_EXCEPTION("dbaccess");
951 Reference<XDataSource> ODatabaseModelImpl::getOrCreateDataSource()
953 rtl::Reference<ODatabaseSource> xDs = m_xDataSource;
954 if ( !xDs.is() )
956 xDs = new ODatabaseSource(this);
957 m_xDataSource = xDs.get();
959 return xDs;
962 rtl::Reference<ODatabaseDocument> ODatabaseModelImpl::getModel_noCreate() const
964 return m_xModel.get();
967 rtl::Reference< ODatabaseDocument > ODatabaseModelImpl::createNewModel_deliverOwnership()
969 rtl::Reference< ODatabaseDocument > xModel( m_xModel );
970 OSL_PRECOND( !xModel.is(), "ODatabaseModelImpl::createNewModel_deliverOwnership: not to be called if there already is a model!" );
971 if ( !xModel.is() )
973 bool bHadModelBefore = m_bDocumentInitialized;
975 xModel = ODatabaseDocument::createDatabaseDocument( this, ODatabaseDocument::FactoryAccess() );
976 m_xModel = xModel.get();
980 Reference< XGlobalEventBroadcaster > xModelCollection = theGlobalEventBroadcaster::get( m_aContext );
981 xModelCollection->insert( Any( Reference< XModel >(xModel) ) );
983 catch( const Exception& )
985 DBG_UNHANDLED_EXCEPTION("dbaccess");
988 if ( bHadModelBefore )
990 // do an attachResources
991 // In case the document is loaded regularly, this is not necessary, as our loader will do it.
992 // However, in case that the document is implicitly created by asking the data source for the document,
993 // then nobody would call the doc's attachResource. So, we do it here, to ensure it's in a proper
994 // state, fires all events, and so on.
995 // #i105505#
996 xModel->attachResource( xModel->getURL(), m_aMediaDescriptor.getPropertyValues() );
999 return xModel;
1002 void ODatabaseModelImpl::acquire()
1004 osl_atomic_increment(&m_refCount);
1007 void ODatabaseModelImpl::release()
1009 if ( osl_atomic_decrement(&m_refCount) == 0 )
1011 acquire(); // prevent multiple releases
1012 m_rDBContext.removeFromTerminateListener(*this);
1013 dispose();
1014 m_rDBContext.storeTransientProperties(*this);
1015 if (!m_sDocumentURL.isEmpty())
1016 m_rDBContext.revokeDatabaseDocument(*this);
1017 delete this;
1021 void ODatabaseModelImpl::commitStorages()
1023 getDocumentStorageAccess()->commitStorages();
1026 Reference< XStorage > ODatabaseModelImpl::getStorage( const ObjectType _eType )
1028 return getDocumentStorageAccess()->getDocumentSubStorage( getObjectContainerStorageName( _eType ),
1029 css::embed::ElementModes::READWRITE );
1032 // static
1033 std::span<const DefaultPropertyValue> ODatabaseModelImpl::getDefaultDataSourceSettings()
1035 static const DefaultPropertyValue aKnownSettings[] =
1037 // known JDBC settings
1038 { u"JavaDriverClass"_ustr, Any( OUString() ) },
1039 { u"JavaDriverClassPath"_ustr, Any( OUString() ) },
1040 { u"IgnoreCurrency"_ustr, Any( false ) },
1041 // known settings for file-based drivers
1042 { u"Extension"_ustr, Any( OUString() ) },
1043 { u"CharSet"_ustr, Any( OUString() ) },
1044 { u"HeaderLine"_ustr, Any( true ) },
1045 { u"FieldDelimiter"_ustr, Any( u","_ustr ) },
1046 { u"StringDelimiter"_ustr, Any( u"\""_ustr ) },
1047 { u"DecimalDelimiter"_ustr, Any( u"."_ustr ) },
1048 { u"ThousandDelimiter"_ustr, Any( OUString() ) },
1049 { u"ShowDeleted"_ustr, Any( false ) },
1050 // known ODBC settings
1051 { u"SystemDriverSettings"_ustr, Any( OUString() ) },
1052 { u"UseCatalog"_ustr, Any( false ) },
1053 { u"TypeInfoSettings"_ustr, Any( Sequence< Any >()) },
1054 // settings related to auto increment handling
1055 { u"AutoIncrementCreation"_ustr, Any( OUString() ) },
1056 { u"AutoRetrievingStatement"_ustr, Any( OUString() ) },
1057 { u"IsAutoRetrievingEnabled"_ustr, Any( false ) },
1058 // known LDAP driver settings
1059 { u"HostName"_ustr, Any( OUString() ) },
1060 { u"PortNumber"_ustr, Any( sal_Int32(389) ) },
1061 { u"BaseDN"_ustr, Any( OUString() ) },
1062 { u"MaxRowCount"_ustr, Any( sal_Int32(100) ) },
1063 // known MySQLNative driver settings
1064 { u"LocalSocket"_ustr, Any( OUString() ) },
1065 { u"NamedPipe"_ustr, Any( OUString() ) },
1066 // misc known driver settings
1067 { u"ParameterNameSubstitution"_ustr, Any( false ) },
1068 { u"AddIndexAppendix"_ustr, Any( true ) },
1069 { u"IgnoreDriverPrivileges"_ustr, Any( true ) },
1070 { u"ImplicitCatalogRestriction"_ustr, ::cppu::UnoType< OUString >::get() },
1071 { u"ImplicitSchemaRestriction"_ustr, ::cppu::UnoType< OUString >::get() },
1072 { u"PrimaryKeySupport"_ustr, ::cppu::UnoType< sal_Bool >::get() },
1073 { u"ShowColumnDescription"_ustr, Any( false ) },
1074 // known SDB level settings
1075 { u"NoNameLengthLimit"_ustr, Any( false ) },
1076 { u"AppendTableAliasName"_ustr, Any( false ) },
1077 { u"GenerateASBeforeCorrelationName"_ustr, Any( false ) },
1078 { u"ColumnAliasInOrderBy"_ustr, Any( true ) },
1079 { u"EnableSQL92Check"_ustr, Any( false ) },
1080 { u"BooleanComparisonMode"_ustr, Any( BooleanComparisonMode::EQUAL_INTEGER ) },
1081 { u"TableTypeFilterMode"_ustr, Any( sal_Int32(3) ) },
1082 { u"RespectDriverResultSetType"_ustr, Any( false ) },
1083 { u"UseSchemaInSelect"_ustr, Any( true ) },
1084 { u"UseCatalogInSelect"_ustr, Any( true ) },
1085 { u"EnableOuterJoinEscape"_ustr, Any( true ) },
1086 { u"PreferDosLikeLineEnds"_ustr, Any( false ) },
1087 { u"FormsCheckRequiredFields"_ustr, Any( true ) },
1088 { u"EscapeDateTime"_ustr, Any( true ) },
1090 // known services to handle database tasks
1091 { u"TableAlterationServiceName"_ustr, Any( OUString() ) },
1092 { u"TableRenameServiceName"_ustr, Any( OUString() ) },
1093 { u"ViewAlterationServiceName"_ustr, Any( OUString() ) },
1094 { u"ViewAccessServiceName"_ustr, Any( OUString() ) },
1095 { u"CommandDefinitions"_ustr, Any( OUString() ) },
1096 { u"Forms"_ustr, Any( OUString() ) },
1097 { u"Reports"_ustr, Any( OUString() ) },
1098 { u"KeyAlterationServiceName"_ustr, Any( OUString() ) },
1099 { u"IndexAlterationServiceName"_ustr, Any( OUString() ) },
1101 return aKnownSettings;
1104 TContentPtr& ODatabaseModelImpl::getObjectContainer( ObjectType _eType )
1106 TContentPtr& rContentPtr = m_aContainer[ _eType ];
1108 if ( !rContentPtr )
1110 rContentPtr = std::make_shared<ODefinitionContainer_Impl>();
1111 rContentPtr->m_pDataSource = this;
1112 rContentPtr->m_aProps.aTitle = lcl_getContainerStorageName_throw( _eType );
1114 return rContentPtr;
1117 bool ODatabaseModelImpl::adjustMacroMode_AutoReject()
1119 return m_aMacroMode.adjustMacroMode( nullptr );
1122 bool ODatabaseModelImpl::checkMacrosOnLoading()
1124 Reference< XInteractionHandler > xInteraction;
1125 xInteraction = m_aMediaDescriptor.getOrDefault( u"InteractionHandler"_ustr, xInteraction );
1126 const bool bHasMacros = m_aMacroMode.hasMacros();
1127 return m_aMacroMode.checkMacrosOnLoading(xInteraction, false /*HasValidContentSignature*/, bHasMacros);
1130 void ODatabaseModelImpl::resetMacroExecutionMode()
1132 m_aMacroMode = ::sfx2::DocumentMacroMode( *this );
1135 Reference< XStorageBasedLibraryContainer > ODatabaseModelImpl::getLibraryContainer( bool _bScript )
1137 Reference< XStorageBasedLibraryContainer >& rxContainer( _bScript ? m_xBasicLibraries : m_xDialogLibraries );
1138 if ( rxContainer.is() )
1139 return rxContainer;
1141 rtl::Reference< ODatabaseDocument > xDocument( getModel_noCreate() );
1142 if (!xDocument)
1143 throw uno::RuntimeException();
1144 // this is only to be called if there already exists a document model - in fact, it is
1145 // to be called by the document model only
1149 Reference< XStorageBasedLibraryContainer > (*Factory)( const Reference< XComponentContext >&, const Reference< XStorageBasedDocument >&)
1150 = _bScript ? &DocumentScriptLibraryContainer::create : &DocumentDialogLibraryContainer::create;
1152 rxContainer.set(
1153 (*Factory)( m_aContext, xDocument ),
1154 UNO_SET_THROW
1157 catch( const RuntimeException& )
1159 throw;
1161 catch( const Exception& )
1163 throw WrappedTargetRuntimeException(
1164 OUString(),
1165 cppu::getXWeak(xDocument.get()),
1166 ::cppu::getCaughtException()
1169 return rxContainer;
1172 void ODatabaseModelImpl::storeLibraryContainersTo( const Reference< XStorage >& _rxToRootStorage )
1174 if ( m_xBasicLibraries.is() )
1175 m_xBasicLibraries->storeLibrariesToStorage( _rxToRootStorage );
1177 if ( m_xDialogLibraries.is() )
1178 m_xDialogLibraries->storeLibrariesToStorage( _rxToRootStorage );
1181 Reference< XStorage > ODatabaseModelImpl::switchToStorage( const Reference< XStorage >& _rxNewRootStorage )
1183 if ( !_rxNewRootStorage.is() )
1184 throw IllegalArgumentException();
1186 return impl_switchToStorage_throw( _rxNewRootStorage );
1189 namespace
1191 void lcl_modifyListening( ::sfx2::IModifiableDocument& _rDocument,
1192 const Reference< XStorage >& _rxStorage, ::rtl::Reference< ::sfx2::DocumentStorageModifyListener >& _inout_rListener,
1193 comphelper::SolarMutex& _rMutex, bool _bListen )
1195 Reference< XModifiable > xModify( _rxStorage, UNO_QUERY );
1196 OSL_ENSURE( xModify.is() || !_rxStorage.is(), "lcl_modifyListening: storage can't notify us!" );
1198 if ( xModify.is() && !_bListen && _inout_rListener.is() )
1200 xModify->removeModifyListener( _inout_rListener );
1203 if ( _inout_rListener.is() )
1205 _inout_rListener->dispose();
1206 _inout_rListener = nullptr;
1209 if ( xModify.is() && _bListen )
1211 _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument, _rMutex );
1212 xModify->addModifyListener( _inout_rListener );
1217 namespace
1219 void lcl_rebaseScriptStorage_throw( const Reference< XStorageBasedLibraryContainer >& _rxContainer,
1220 const Reference< XStorage >& _rxNewRootStorage )
1222 if ( _rxContainer.is() )
1224 if ( _rxNewRootStorage.is() )
1225 _rxContainer->setRootStorage( _rxNewRootStorage );
1226 // else
1227 // TODO: what to do here? dispose the container?
1232 Reference< XStorage > const & ODatabaseModelImpl::impl_switchToStorage_throw( const Reference< XStorage >& _rxNewRootStorage )
1234 // stop listening for modifications at the old storage
1235 lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, Application::GetSolarMutex(), false );
1237 // set new storage
1238 m_xDocumentStorage.reset( _rxNewRootStorage, SharedStorage::TakeOwnership );
1240 // start listening for modifications
1241 lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, Application::GetSolarMutex(), true );
1243 // forward new storage to Basic and Dialog library containers
1244 lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() );
1245 lcl_rebaseScriptStorage_throw( m_xDialogLibraries, m_xDocumentStorage.getTyped() );
1247 m_bReadOnly = !tools::stor::storageIsWritable_nothrow( m_xDocumentStorage.getTyped() );
1248 // TODO: our data source, if it exists, must broadcast the change of its ReadOnly property
1250 return m_xDocumentStorage.getTyped();
1253 void ODatabaseModelImpl::impl_switchToLogicalURL( const OUString& i_rDocumentURL )
1255 if ( i_rDocumentURL == m_sDocumentURL )
1256 return;
1258 const OUString sOldURL( m_sDocumentURL );
1259 // update our name, if necessary
1260 if ( ( m_sName == m_sDocumentURL ) // our name is our old URL
1261 || ( m_sName.isEmpty() ) // we do not have a name, yet (i.e. are not registered at the database context)
1264 INetURLObject aURL( i_rDocumentURL );
1265 if ( aURL.GetProtocol() != INetProtocol::NotValid )
1267 m_sName = i_rDocumentURL;
1268 // TODO: our data source must broadcast the change of the Name property
1272 // remember URL
1273 m_sDocumentURL = i_rDocumentURL;
1275 // update our location, if necessary
1276 if ( m_sDocFileLocation.isEmpty() )
1277 m_sDocFileLocation = m_sDocumentURL;
1279 // register at the database context, or change registration
1280 if (!sOldURL.isEmpty())
1281 m_rDBContext.databaseDocumentURLChange( sOldURL, m_sDocumentURL );
1282 else
1283 m_rDBContext.registerDatabaseDocument( *this );
1286 OUString ODatabaseModelImpl::getObjectContainerStorageName( const ObjectType _eType )
1288 return lcl_getContainerStorageName_throw( _eType );
1291 sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const
1293 sal_Int16 nCurrentMode = MacroExecMode::NEVER_EXECUTE;
1296 nCurrentMode = m_aMediaDescriptor.getOrDefault( u"MacroExecutionMode"_ustr, nCurrentMode );
1298 catch( const Exception& )
1300 DBG_UNHANDLED_EXCEPTION("dbaccess");
1302 return nCurrentMode;
1305 void ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode )
1307 m_aMediaDescriptor.put( u"MacroExecutionMode"_ustr, nMacroMode );
1310 OUString ODatabaseModelImpl::getDocumentLocation() const
1312 return getURL();
1313 // formerly, we returned getDocFileLocation here, which is the location of the file from which we
1314 // recovered the "real" document.
1315 // However, during CWS autorecovery evolving, we clarified (with MAV/MT) the role of XModel::getURL and
1316 // XStorable::getLocation. In this course, we agreed that for a macro security check, the *document URL*
1317 // (not the recovery file URL) is to be used: The recovery file lies in the backup folder, and by definition,
1318 // this folder is considered to be secure. So, the document URL needs to be used to decide about the security.
1321 ODatabaseModelImpl::EmbeddedMacros ODatabaseModelImpl::determineEmbeddedMacros()
1323 if ( !m_aEmbeddedMacros )
1325 if ( ::sfx2::DocumentMacroMode::storageHasMacros( getOrCreateRootStorage() ) )
1327 m_aEmbeddedMacros = EmbeddedMacros::DocumentWide;
1329 else if ( lcl_hasObjectsWithMacros_nothrow( *this, ObjectType::Form )
1330 || lcl_hasObjectsWithMacros_nothrow( *this, ObjectType::Report )
1333 m_aEmbeddedMacros = EmbeddedMacros::SubDocument;
1335 else
1337 m_aEmbeddedMacros = EmbeddedMacros::NONE;
1340 return *m_aEmbeddedMacros;
1343 bool ODatabaseModelImpl::documentStorageHasMacros() const
1345 const_cast< ODatabaseModelImpl* >( this )->determineEmbeddedMacros();
1346 return ( *m_aEmbeddedMacros != EmbeddedMacros::NONE );
1349 bool ODatabaseModelImpl::macroCallsSeenWhileLoading() const
1351 return m_bMacroCallsSeenWhileLoading;
1354 Reference< XEmbeddedScripts > ODatabaseModelImpl::getEmbeddedDocumentScripts() const
1356 return getModel_noCreate();
1359 SignatureState ODatabaseModelImpl::getScriptingSignatureState()
1361 return m_nScriptingSignatureState;
1364 bool ODatabaseModelImpl::hasTrustedScriptingSignature(
1365 const css::uno::Reference<css::task::XInteractionHandler>& _rxInteraction)
1367 bool bResult = false;
1371 // Don't use m_xDocumentStorage, that somehow has an incomplete storage representation
1372 // which leads to signatures not being found
1373 Reference<XStorage> xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
1374 ZIP_STORAGE_FORMAT_STRING, m_sDocFileLocation, ElementModes::READ);
1376 OUString aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(getOrCreateRootStorage()));
1377 uno::Reference<security::XDocumentDigitalSignatures> xSigner(
1378 security::DocumentDigitalSignatures::createWithVersion(
1379 comphelper::getProcessComponentContext(), aODFVersion));
1380 const uno::Sequence<security::DocumentSignatureInformation> aInfo
1381 = xSigner->verifyScriptingContentSignatures(xStorage,
1382 uno::Reference<io::XInputStream>());
1384 if (!aInfo.hasElements())
1385 return false;
1387 m_nScriptingSignatureState = DocumentSignatures::getSignatureState(aInfo);
1388 if (m_nScriptingSignatureState == SignatureState::OK
1389 || m_nScriptingSignatureState == SignatureState::NOTVALIDATED)
1391 bResult = std::any_of(aInfo.begin(), aInfo.end(),
1392 [&xSigner](const security::DocumentSignatureInformation& rInfo) {
1393 return xSigner->isAuthorTrusted(rInfo.Signer);
1397 if (!bResult && _rxInteraction)
1399 task::DocumentMacroConfirmationRequest aRequest;
1400 aRequest.DocumentURL = m_sDocFileLocation;
1401 aRequest.DocumentStorage = std::move(xStorage);
1402 aRequest.DocumentSignatureInformation = aInfo;
1403 aRequest.DocumentVersion = aODFVersion;
1404 aRequest.Classification = task::InteractionClassification_QUERY;
1405 bResult = SfxMedium::CallApproveHandler(_rxInteraction, uno::Any(aRequest), true);
1408 catch (uno::Exception&)
1412 return bResult;
1415 void ODatabaseModelImpl::storageIsModified()
1417 setModified( true );
1420 ModelDependentComponent::ModelDependentComponent( ::rtl::Reference< ODatabaseModelImpl > _model )
1421 :m_pImpl(std::move( _model ))
1425 ModelDependentComponent::~ModelDependentComponent()
1429 } // namespace dbaccess
1431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */