1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
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
;
98 explicit DocumentStorageAccess( ODatabaseModelImpl
& _rModelImplementation
)
99 :m_pModelImplementation( &_rModelImplementation
)
100 ,m_bPropagateCommitToRoot( true )
101 ,m_bDisposingSubStorages( false )
106 virtual ~DocumentStorageAccess() override
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
;
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
);
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
) )
193 xStorage
= xRootStorage
->openStorageElement( _rStorageName
, nRealMode
);
195 Reference
< XTransactionBroadcaster
> xBroad( xStorage
, UNO_QUERY
);
197 xBroad
->addTransactionListener( this );
200 catch( const Exception
& )
202 DBG_UNHANDLED_EXCEPTION("dbaccess");
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
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
);
258 DBG_UNHANDLED_EXCEPTION("dbaccess");
261 if ( _bPreventRootCommits
)
262 impl_resumeCommitPropagation();
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
;
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*/ )
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
) )
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*/ )
333 void SAL_CALL
DocumentStorageAccess::reverted( const css::lang::EventObject
& /*aEvent*/ )
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
)
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
)
355 ,m_aMacroMode( *this )
356 ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE
)
357 ,m_rDBContext( _rDBContext
)
359 ,m_bModificationLock( false )
360 ,m_bDocumentInitialized( false )
361 ,m_nScriptingSignatureState(SignatureState::UNKNOWN
)
362 ,m_aContext( _rxContext
)
365 ,m_bPasswordRequired(false)
366 ,m_bSuppressVersionColumns(true)
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
384 ,m_aMacroMode( *this )
385 ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE
)
386 ,m_rDBContext( _rDBContext
)
388 ,m_bModificationLock( false )
389 ,m_bDocumentInitialized( false )
390 ,m_nScriptingSignatureState(SignatureState::UNKNOWN
)
391 ,m_aContext( _rxContext
)
392 ,m_sName(std::move(_sRegistrationName
))
395 ,m_bPasswordRequired(false)
396 ,m_bSuppressVersionColumns(true)
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
,
436 PropertyAttribute::BOUND
| PropertyAttribute::MAYBEDEFAULT
| PropertyAttribute::MAYBEVOID
438 xSettingsSet
->insert( Any( aProperty
) );
442 xContainer
->addProperty(setting
.Name
,
443 PropertyAttribute::BOUND
| PropertyAttribute::MAYBEDEFAULT
,
449 catch( const Exception
& )
451 DBG_UNHANDLED_EXCEPTION("dbaccess");
453 m_rDBContext
.appendAtTerminateListener(*this);
458 OUString
lcl_getContainerStorageName_throw( ODatabaseModelImpl::ObjectType _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;
468 throw RuntimeException();
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
)
491 bSomeDocHasMacros
= ODatabaseModelImpl::objectHasMacros( _rxContainerStorage
, rPersistentName
);
492 if (bSomeDocHasMacros
)
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
) )
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");
553 void ODatabaseModelImpl::reset()
556 for (auto & i
: m_aContainer
)
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
);
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
>();
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
)
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
);
631 m_xDataSource
.clear();
634 rtl::Reference
< ODatabaseDocument
> xModel( m_xModel
);
641 catch( const Exception
& )
643 DBG_UNHANDLED_EXCEPTION("dbaccess");
645 m_xDataSource
.clear();
648 for (auto const& elem
: m_aContainer
)
651 elem
->m_pDataSource
= nullptr;
653 for (auto & i
: m_aContainer
)
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
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
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
);
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
;
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
)
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
);
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
,
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
);
918 SAL_WARN("dbaccess", "An invalid signature was copied!");
923 catch (uno::Exception
&)
925 TOOLS_WARN_EXCEPTION("dbaccess", "");
932 void ODatabaseModelImpl::setModified( bool _bModified
)
934 if ( isModifyLocked() )
939 rtl::Reference
< ODatabaseDocument
> xModi( m_xModel
);
941 xModi
->setModified( _bModified
);
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
;
956 xDs
= new ODatabaseSource(this);
957 m_xDataSource
= xDs
.get();
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!" );
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.
996 xModel
->attachResource( xModel
->getURL(), m_aMediaDescriptor
.getPropertyValues() );
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);
1014 m_rDBContext
.storeTransientProperties(*this);
1015 if (!m_sDocumentURL
.isEmpty())
1016 m_rDBContext
.revokeDatabaseDocument(*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
);
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
];
1110 rContentPtr
= std::make_shared
<ODefinitionContainer_Impl
>();
1111 rContentPtr
->m_pDataSource
= this;
1112 rContentPtr
->m_aProps
.aTitle
= lcl_getContainerStorageName_throw( _eType
);
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() )
1141 rtl::Reference
< ODatabaseDocument
> xDocument( getModel_noCreate() );
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
;
1153 (*Factory
)( m_aContext
, xDocument
),
1157 catch( const RuntimeException
& )
1161 catch( const Exception
& )
1163 throw WrappedTargetRuntimeException(
1165 cppu::getXWeak(xDocument
.get()),
1166 ::cppu::getCaughtException()
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
);
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
);
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
);
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 );
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
)
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
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
);
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
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
;
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())
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
&)
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: */