1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include "commandcontainer.hxx" 21 #include "connection.hxx" 22 #include <databasecontext.hxx> 23 #include "databasedocument.hxx" 24 #include "datasource.hxx" 25 #include <stringconstants.hxx> 26 #include <ModelImpl.hxx> 27 #include <sdbcoretools.hxx> 28 29 #include <com/sun/star/beans/PropertyBag.hpp> 30 #include <com/sun/star/container/XSet.hpp> 31 #include <com/sun/star/document/MacroExecMode.hpp> 32 #include <com/sun/star/embed/XTransactedObject.hpp> 33 #include <com/sun/star/embed/XTransactionBroadcaster.hpp> 34 #include <com/sun/star/embed/StorageFactory.hpp> 35 #include <com/sun/star/form/XLoadable.hpp> 36 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp> 37 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> 38 #include <com/sun/star/sdb/BooleanComparisonMode.hpp> 39 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp> 40 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp> 41 #include <com/sun/star/util/NumberFormatsSupplier.hpp> 42 43 #include <connectivity/dbexception.hxx> 44 #include <cppuhelper/exc_hlp.hxx> 45 #include <cppuhelper/implbase.hxx> 46 #include <cppuhelper/typeprovider.hxx> 47 #include <comphelper/types.hxx> 48 #include <rtl/digest.h> 49 #include <sfx2/signaturestate.hxx> 50 #include <tools/debug.hxx> 51 #include <tools/diagnose_ex.h> 52 #include <osl/diagnose.h> 53 #include <sal/log.hxx> 54 #include <vcl/errcode.hxx> 55 #include <tools/urlobj.hxx> 56 #include <unotools/sharedunocomponent.hxx> 57 #include <unotools/configmgr.hxx> 58 #include <i18nlangtag/languagetag.hxx> 59 60 #include <algorithm> 61 62 using namespace ::com::sun::star::document; 63 using namespace ::com::sun::star::sdbc; 64 using namespace ::com::sun::star::sdbcx; 65 using namespace ::com::sun::star::sdb; 66 using namespace ::com::sun::star::beans; 67 using namespace ::com::sun::star::uno; 68 using namespace ::com::sun::star::lang; 69 using namespace ::com::sun::star::embed; 70 using namespace ::com::sun::star::container; 71 using namespace ::com::sun::star::util; 72 using namespace ::com::sun::star::io; 73 using namespace ::com::sun::star::ucb; 74 using namespace ::com::sun::star::frame; 75 using namespace ::com::sun::star::view; 76 using namespace ::com::sun::star::task; 77 using namespace ::com::sun::star::script; 78 using namespace ::cppu; 79 using namespace ::osl; 80 using namespace ::dbtools; 81 using namespace ::comphelper; 82 83 namespace dbaccess 84 { 85 86 // DocumentStorageAccess 87 class DocumentStorageAccess : public ::cppu::WeakImplHelper< XDocumentSubStorageSupplier 88 , XTransactionListener > 89 { 90 typedef std::map< OUString, Reference< XStorage > > NamedStorages; 91 92 ::osl::Mutex m_aMutex; 93 /// all sub storages which we ever gave to the outer world 94 NamedStorages m_aExposedStorages; 95 ODatabaseModelImpl* m_pModelImplementation; 96 bool m_bPropagateCommitToRoot; 97 bool m_bDisposingSubStorages; 98 99 public: 100 explicit DocumentStorageAccess( ODatabaseModelImpl& _rModelImplementation ) 101 :m_pModelImplementation( &_rModelImplementation ) 102 ,m_bPropagateCommitToRoot( true ) 103 ,m_bDisposingSubStorages( false ) 104 { 105 } 106 107 protected: 108 virtual ~DocumentStorageAccess() override 109 { 110 } 111 112 public: 113 void dispose(); 114 115 // XDocumentSubStorageSupplier 116 virtual Reference< XStorage > SAL_CALL getDocumentSubStorage( const OUString& aStorageName, ::sal_Int32 _nMode ) override; 117 virtual Sequence< OUString > SAL_CALL getDocumentSubStoragesNames( ) override; 118 119 // XTransactionListener 120 virtual void SAL_CALL preCommit( const css::lang::EventObject& aEvent ) override; 121 virtual void SAL_CALL commited( const css::lang::EventObject& aEvent ) override; 122 virtual void SAL_CALL preRevert( const css::lang::EventObject& aEvent ) override; 123 virtual void SAL_CALL reverted( const css::lang::EventObject& aEvent ) override; 124 125 // XEventListener 126 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; 127 128 /// disposes all storages managed by this instance 129 void disposeStorages(); 130 131 /// disposes all known sub storages 132 void commitStorages(); 133 134 /// commits the dedicated "database" storage 135 bool commitEmbeddedStorage( bool _bPreventRootCommits ); 136 137 private: 138 /** opens the sub storage with the given name, in the given mode 139 */ 140 Reference< XStorage > impl_openSubStorage_nothrow( const OUString& _rStorageName, sal_Int32 _nMode ); 141 142 void impl_suspendCommitPropagation() 143 { 144 OSL_ENSURE( m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_suspendCommitPropagation: already suspended" ); 145 m_bPropagateCommitToRoot = false; 146 } 147 void impl_resumeCommitPropagation() 148 { 149 OSL_ENSURE( !m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_resumeCommitPropagation: not suspended" ); 150 m_bPropagateCommitToRoot = true; 151 } 152 153 }; 154 155 void DocumentStorageAccess::dispose() 156 { 157 ::osl::MutexGuard aGuard( m_aMutex ); 158 159 for (auto const& exposedStorage : m_aExposedStorages) 160 { 161 try 162 { 163 Reference< XTransactionBroadcaster > xBroadcaster(exposedStorage.second, UNO_QUERY); 164 if ( xBroadcaster.is() ) 165 xBroadcaster->removeTransactionListener( this ); 166 } 167 catch( const Exception& ) 168 { 169 DBG_UNHANDLED_EXCEPTION("dbaccess"); 170 } 171 } 172 173 m_aExposedStorages.clear(); 174 175 m_pModelImplementation = nullptr; 176 } 177 178 Reference< XStorage > DocumentStorageAccess::impl_openSubStorage_nothrow( const OUString& _rStorageName, sal_Int32 _nDesiredMode ) 179 { 180 OSL_ENSURE( !_rStorageName.isEmpty(),"ODatabaseModelImpl::impl_openSubStorage_nothrow: Invalid storage name!" ); 181 182 Reference< XStorage > xStorage; 183 try 184 { 185 Reference< XStorage > xRootStorage( m_pModelImplementation->getOrCreateRootStorage() ); 186 if ( xRootStorage.is() ) 187 { 188 sal_Int32 nRealMode = m_pModelImplementation->m_bDocumentReadOnly ? ElementModes::READ : _nDesiredMode; 189 if ( nRealMode == ElementModes::READ ) 190 { 191 if ( xRootStorage.is() && !xRootStorage->hasByName( _rStorageName ) ) 192 return xStorage; 193 } 194 195 xStorage = xRootStorage->openStorageElement( _rStorageName, nRealMode ); 196 197 Reference< XTransactionBroadcaster > xBroad( xStorage, UNO_QUERY ); 198 if ( xBroad.is() ) 199 xBroad->addTransactionListener( this ); 200 } 201 } 202 catch( const Exception& ) 203 { 204 DBG_UNHANDLED_EXCEPTION("dbaccess"); 205 } 206 207 return xStorage; 208 } 209 210 void DocumentStorageAccess::disposeStorages() 211 { 212 m_bDisposingSubStorages = true; 213 214 for (auto & exposedStorage : m_aExposedStorages) 215 { 216 try 217 { 218 ::comphelper::disposeComponent( exposedStorage.second ); 219 } 220 catch( const Exception& ) 221 { 222 DBG_UNHANDLED_EXCEPTION("dbaccess"); 223 } 224 } 225 m_aExposedStorages.clear(); 226 227 m_bDisposingSubStorages = false; 228 } 229 230 void DocumentStorageAccess::commitStorages() 231 { 232 try 233 { 234 for (auto const& exposedStorage : m_aExposedStorages) 235 { 236 tools::stor::commitStorageIfWriteable( exposedStorage.second ); 237 } 238 } 239 catch(const WrappedTargetException&) 240 { 241 // WrappedTargetException not allowed to leave 242 throw IOException(); 243 } 244 } 245 246 bool DocumentStorageAccess::commitEmbeddedStorage( bool _bPreventRootCommits ) 247 { 248 if ( _bPreventRootCommits ) 249 impl_suspendCommitPropagation(); 250 251 bool bSuccess = false; 252 try 253 { 254 NamedStorages::const_iterator pos = m_aExposedStorages.find( "database" ); 255 if ( pos != m_aExposedStorages.end() ) 256 bSuccess = tools::stor::commitStorageIfWriteable( pos->second ); 257 } 258 catch( Exception& ) 259 { 260 DBG_UNHANDLED_EXCEPTION("dbaccess"); 261 } 262 263 if ( _bPreventRootCommits ) 264 impl_resumeCommitPropagation(); 265 266 return bSuccess; 267 268 } 269 270 Reference< XStorage > SAL_CALL DocumentStorageAccess::getDocumentSubStorage( const OUString& aStorageName, ::sal_Int32 _nDesiredMode ) 271 { 272 ::osl::MutexGuard aGuard( m_aMutex ); 273 NamedStorages::const_iterator pos = m_aExposedStorages.find( aStorageName ); 274 if ( pos == m_aExposedStorages.end() ) 275 { 276 Reference< XStorage > xResult = impl_openSubStorage_nothrow( aStorageName, _nDesiredMode ); 277 pos = m_aExposedStorages.emplace( aStorageName, xResult ).first; 278 } 279 280 return pos->second; 281 } 282 283 Sequence< OUString > SAL_CALL DocumentStorageAccess::getDocumentSubStoragesNames( ) 284 { 285 Reference< XStorage > xRootStor( m_pModelImplementation->getRootStorage() ); 286 if ( !xRootStor.is() ) 287 return Sequence< OUString >(); 288 289 std::vector< OUString > aNames; 290 291 Sequence< OUString > aElementNames( xRootStor->getElementNames() ); 292 for ( sal_Int32 i=0; i<aElementNames.getLength(); ++i ) 293 { 294 if ( xRootStor->isStorageElement( aElementNames[i] ) ) 295 aNames.push_back( aElementNames[i] ); 296 } 297 return aNames.empty() 298 ? Sequence< OUString >() 299 : Sequence< OUString >( &aNames[0], aNames.size() ); 300 } 301 302 void SAL_CALL DocumentStorageAccess::preCommit( const css::lang::EventObject& /*aEvent*/ ) 303 { 304 // not interested in 305 } 306 307 void SAL_CALL DocumentStorageAccess::commited( const css::lang::EventObject& aEvent ) 308 { 309 ::osl::MutexGuard aGuard( m_aMutex ); 310 311 if ( m_pModelImplementation ) 312 m_pModelImplementation->setModified( true ); 313 314 if ( m_pModelImplementation && m_bPropagateCommitToRoot ) 315 { 316 Reference< XStorage > xStorage( aEvent.Source, UNO_QUERY ); 317 318 // check if this is the dedicated "database" sub storage 319 NamedStorages::const_iterator pos = m_aExposedStorages.find( "database" ); 320 if ( ( pos != m_aExposedStorages.end() ) 321 && ( pos->second == xStorage ) 322 ) 323 { 324 // if so, also commit the root storage 325 m_pModelImplementation->commitRootStorage(); 326 } 327 } 328 } 329 330 void SAL_CALL DocumentStorageAccess::preRevert( const css::lang::EventObject& /*aEvent*/ ) 331 { 332 // not interested in 333 } 334 335 void SAL_CALL DocumentStorageAccess::reverted( const css::lang::EventObject& /*aEvent*/ ) 336 { 337 // not interested in 338 } 339 340 void SAL_CALL DocumentStorageAccess::disposing( const css::lang::EventObject& Source ) 341 { 342 OSL_ENSURE( Reference< XStorage >( Source.Source, UNO_QUERY ).is(), "DocumentStorageAccess::disposing: No storage? What's this?" ); 343 344 if ( m_bDisposingSubStorages ) 345 return; 346 347 auto find = std::find_if(m_aExposedStorages.begin(), m_aExposedStorages.end(), 348 [&Source](const NamedStorages::value_type& rEntry) { return rEntry.second == Source.Source; }); 349 if (find != m_aExposedStorages.end()) 350 m_aExposedStorages.erase( find ); 351 } 352 353 // ODatabaseModelImpl 354 355 ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XComponentContext >& _rxContext, ODatabaseContext& _rDBContext ) 356 :m_xModel() 357 ,m_xDataSource() 358 ,m_aContainer(4) 359 ,m_aMacroMode( *this ) 360 ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE ) 361 ,m_rDBContext( _rDBContext ) 362 ,m_refCount(0) 363 ,m_aEmbeddedMacros() 364 ,m_bModificationLock( false ) 365 ,m_bDocumentInitialized( false ) 366 ,m_aContext( _rxContext ) 367 ,m_nLoginTimeout(0) 368 ,m_bReadOnly(false) 369 ,m_bPasswordRequired(false) 370 ,m_bSuppressVersionColumns(true) 371 ,m_bModified(false) 372 ,m_bDocumentReadOnly(false) 373 ,m_pSharedConnectionManager(nullptr) 374 ,m_nControllerLockCount(0) 375 { 376 // some kind of default 377 m_sConnectURL = "jdbc:"; 378 m_aTableFilter.realloc(1); 379 m_aTableFilter[0] = "%"; 380 impl_construct_nothrow(); 381 } 382 383 ODatabaseModelImpl::ODatabaseModelImpl( 384 const OUString& _rRegistrationName, 385 const Reference< XComponentContext >& _rxContext, 386 ODatabaseContext& _rDBContext 387 ) 388 :m_xModel() 389 ,m_xDataSource() 390 ,m_aContainer(4) 391 ,m_aMacroMode( *this ) 392 ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE ) 393 ,m_rDBContext( _rDBContext ) 394 ,m_refCount(0) 395 ,m_aEmbeddedMacros() 396 ,m_bModificationLock( false ) 397 ,m_bDocumentInitialized( false ) 398 ,m_aContext( _rxContext ) 399 ,m_sName(_rRegistrationName) 400 ,m_nLoginTimeout(0) 401 ,m_bReadOnly(false) 402 ,m_bPasswordRequired(false) 403 ,m_bSuppressVersionColumns(true) 404 ,m_bModified(false) 405 ,m_bDocumentReadOnly(false) 406 ,m_pSharedConnectionManager(nullptr) 407 ,m_nControllerLockCount(0) 408 { 409 impl_construct_nothrow(); 410 } 411 412 ODatabaseModelImpl::~ODatabaseModelImpl() 413 { 414 } 415 416 void ODatabaseModelImpl::impl_construct_nothrow() 417 { 418 // create the property bag to hold the settings (also known as "Info" property) 419 try 420 { 421 // the set of property value types in the bag is limited: 422 Sequence< Type > aAllowedTypes({ 423 cppu::UnoType<sal_Bool>::get(), 424 cppu::UnoType<double>::get(), 425 cppu::UnoType<OUString>::get(), 426 cppu::UnoType<sal_Int32>::get(), 427 cppu::UnoType<sal_Int16>::get(), 428 cppu::UnoType<Sequence< Any >>::get(), 429 }); 430 431 m_xSettings = PropertyBag::createWithTypes( m_aContext, aAllowedTypes, false/*AllowEmptyPropertyName*/, true/*AutomaticAddition*/ ); 432 433 // insert the default settings 434 Reference< XPropertyContainer > xContainer( m_xSettings, UNO_QUERY_THROW ); 435 Reference< XSet > xSettingsSet( m_xSettings, UNO_QUERY_THROW ); 436 const AsciiPropertyValue* pSettings = getDefaultDataSourceSettings(); 437 for ( ; pSettings->AsciiName; ++pSettings ) 438 { 439 if ( !pSettings->DefaultValue.hasValue() ) 440 { 441 Property aProperty( 442 OUString::createFromAscii( pSettings->AsciiName ), 443 -1, 444 pSettings->ValueType, 445 PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID 446 ); 447 xSettingsSet->insert( makeAny( aProperty ) ); 448 } 449 else 450 { 451 xContainer->addProperty( 452 OUString::createFromAscii( pSettings->AsciiName ), 453 PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT, 454 pSettings->DefaultValue 455 ); 456 } 457 } 458 } 459 catch( const Exception& ) 460 { 461 DBG_UNHANDLED_EXCEPTION("dbaccess"); 462 } 463 m_rDBContext.appendAtTerminateListener(*this); 464 } 465 466 namespace 467 { 468 OUString lcl_getContainerStorageName_throw( ODatabaseModelImpl::ObjectType _eType ) 469 { 470 const sal_Char* pAsciiName( nullptr ); 471 switch ( _eType ) 472 { 473 case ODatabaseModelImpl::E_FORM: pAsciiName = "forms"; break; 474 case ODatabaseModelImpl::E_REPORT: pAsciiName = "reports"; break; 475 case ODatabaseModelImpl::E_QUERY: pAsciiName = "queries"; break; 476 case ODatabaseModelImpl::E_TABLE: pAsciiName = "tables"; break; 477 default: 478 throw RuntimeException(); 479 } 480 return OUString::createFromAscii( pAsciiName ); 481 } 482 483 bool lcl_hasObjectWithMacros_throw( const ODefinitionContainer_Impl& _rObjectDefinitions, const Reference< XStorage >& _rxContainerStorage ) 484 { 485 bool bSomeDocHasMacros = false; 486 487 for (auto const& objectDefinition : _rObjectDefinitions) 488 { 489 const TContentPtr& rDefinition( objectDefinition.second ); 490 const OUString& rPersistentName( rDefinition->m_aProps.sPersistentName ); 491 492 if ( rPersistentName.isEmpty() ) 493 { // it's a logical sub folder used to organize the real objects 494 const ODefinitionContainer_Impl& rSubFoldersObjectDefinitions( dynamic_cast< const ODefinitionContainer_Impl& >( *rDefinition ) ); 495 bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rSubFoldersObjectDefinitions, _rxContainerStorage ); 496 if (bSomeDocHasMacros) 497 break; 498 continue; 499 } 500 501 bSomeDocHasMacros = ODatabaseModelImpl::objectHasMacros( _rxContainerStorage, rPersistentName ); 502 if (bSomeDocHasMacros) 503 break; 504 } 505 return bSomeDocHasMacros; 506 } 507 508 bool lcl_hasObjectsWithMacros_nothrow( ODatabaseModelImpl& _rModel, const ODatabaseModelImpl::ObjectType _eType ) 509 { 510 bool bSomeDocHasMacros = false; 511 512 const OContentHelper_Impl& rContainerData( *_rModel.getObjectContainer( _eType ).get() ); 513 const ODefinitionContainer_Impl& rObjectDefinitions = dynamic_cast< const ODefinitionContainer_Impl& >( rContainerData ); 514 515 try 516 { 517 Reference< XStorage > xContainerStorage( _rModel.getStorage( _eType ) ); 518 // note the READWRITE here: If the storage already existed before, then the OpenMode will 519 // be ignored, anyway. 520 // If the storage did not yet exist, then it will be created. If the database document 521 // is read-only, the OpenMode will be automatically downgraded to READ. Otherwise, 522 // the storage will in fact be created as READWRITE. While this is not strictly necessary 523 // for this particular use case here, it is required since the storage is *cached*, and 524 // later use cases will need the READWRITE mode. 525 526 if ( xContainerStorage.is() ) 527 bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rObjectDefinitions, xContainerStorage ); 528 } 529 catch( const Exception& ) 530 { 531 DBG_UNHANDLED_EXCEPTION("dbaccess"); 532 // be on the safe side: If we can't reliably determine whether there are macros, 533 // assume there actually are. Better this way, than the other way round. 534 bSomeDocHasMacros = true; 535 } 536 537 return bSomeDocHasMacros; 538 } 539 } 540 541 bool ODatabaseModelImpl::objectHasMacros( const Reference< XStorage >& _rxContainerStorage, const OUString& _rPersistentName ) 542 { 543 OSL_PRECOND( _rxContainerStorage.is(), "ODatabaseModelImpl::objectHasMacros: this will crash!" ); 544 545 bool bHasMacros = true; 546 try 547 { 548 if ( !_rxContainerStorage->hasByName( _rPersistentName ) ) 549 return false; 550 551 Reference< XStorage > xObjectStor( _rxContainerStorage->openStorageElement( 552 _rPersistentName, ElementModes::READ ) ); 553 554 bHasMacros = ::sfx2::DocumentMacroMode::storageHasMacros( xObjectStor ); 555 } 556 catch( const Exception& ) 557 { 558 DBG_UNHANDLED_EXCEPTION("dbaccess"); 559 } 560 return bHasMacros; 561 } 562 563 void ODatabaseModelImpl::reset() 564 { 565 m_bReadOnly = false; 566 std::vector< TContentPtr > aEmptyContainers( 4 ); 567 m_aContainer.swap( aEmptyContainers ); 568 569 if ( m_pStorageAccess.is() ) 570 { 571 m_pStorageAccess->dispose(); 572 m_pStorageAccess.clear(); 573 } 574 } 575 576 void ODatabaseModelImpl::disposing( const css::lang::EventObject& Source ) 577 { 578 Reference<XConnection> xCon(Source.Source,UNO_QUERY); 579 if ( xCon.is() ) 580 { 581 bool bStore = false; 582 for (OWeakConnectionArray::iterator i = m_aConnections.begin(); i != m_aConnections.end(); ) 583 { 584 css::uno::Reference< css::sdbc::XConnection > xIterConn ( *i ); 585 if ( !xIterConn.is()) 586 { 587 i = m_aConnections.erase(i); 588 } 589 else if ( xCon == xIterConn ) 590 { 591 *i = css::uno::WeakReference< css::sdbc::XConnection >(); 592 bStore = true; 593 break; 594 } else 595 ++i; 596 } 597 598 if ( bStore ) 599 commitRootStorage(); 600 } 601 else 602 { 603 OSL_FAIL( "ODatabaseModelImpl::disposing: where does this come from?" ); 604 } 605 } 606 607 void ODatabaseModelImpl::clearConnections() 608 { 609 OWeakConnectionArray aConnections; 610 aConnections.swap( m_aConnections ); 611 612 Reference< XConnection > xConn; 613 for (auto const& connection : aConnections) 614 { 615 xConn = connection; 616 if ( xConn.is() ) 617 { 618 try 619 { 620 xConn->close(); 621 } 622 catch(const Exception&) 623 { 624 DBG_UNHANDLED_EXCEPTION("dbaccess"); 625 } 626 } 627 } 628 629 m_pSharedConnectionManager = nullptr; 630 m_xSharedConnectionManager = nullptr; 631 } 632 633 void ODatabaseModelImpl::dispose() 634 { 635 // dispose the data source and the model 636 try 637 { 638 Reference< XDataSource > xDS( m_xDataSource ); 639 ::comphelper::disposeComponent( xDS ); 640 641 Reference< XModel > xModel( m_xModel ); 642 ::comphelper::disposeComponent( xModel ); 643 } 644 catch( const Exception& ) 645 { 646 DBG_UNHANDLED_EXCEPTION("dbaccess"); 647 } 648 m_xDataSource = WeakReference<XDataSource>(); 649 m_xModel = WeakReference< XModel >(); 650 651 for (auto const& elem : m_aContainer) 652 { 653 if ( elem.get() ) 654 elem->m_pDataSource = nullptr; 655 } 656 m_aContainer.clear(); 657 658 clearConnections(); 659 660 m_xNumberFormatsSupplier = nullptr; 661 662 try 663 { 664 bool bCouldStore = commitEmbeddedStorage( true ); 665 // "true" means that committing the embedded storage should not trigger committing the root 666 // storage. This is because we are going to commit the root storage ourself, anyway 667 disposeStorages(); 668 if ( bCouldStore ) 669 commitRootStorage(); 670 671 impl_switchToStorage_throw( nullptr ); 672 } 673 catch( const Exception& ) 674 { 675 DBG_UNHANDLED_EXCEPTION("dbaccess"); 676 } 677 678 if ( m_pStorageAccess.is() ) 679 { 680 m_pStorageAccess->dispose(); 681 m_pStorageAccess.clear(); 682 } 683 } 684 685 const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormatsSupplier() 686 { 687 if (!m_xNumberFormatsSupplier.is()) 688 { 689 // the arguments : the work locale of the current user 690 Locale aLocale( LanguageTag::convertToLocale( utl::ConfigManager::getWorkLocale(), false)); 691 692 m_xNumberFormatsSupplier.set( NumberFormatsSupplier::createWithLocale( m_aContext, aLocale ) ); 693 } 694 return m_xNumberFormatsSupplier; 695 } 696 697 void ODatabaseModelImpl::setDocFileLocation( const OUString& i_rLoadedFrom ) 698 { 699 ENSURE_OR_THROW( !i_rLoadedFrom.isEmpty(), "invalid URL" ); 700 m_sDocFileLocation = i_rLoadedFrom; 701 } 702 703 void ODatabaseModelImpl::setResource( const OUString& i_rDocumentURL, const Sequence< PropertyValue >& _rArgs ) 704 { 705 ENSURE_OR_THROW( !i_rDocumentURL.isEmpty(), "invalid URL" ); 706 707 ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs ); 708 #if OSL_DEBUG_LEVEL > 0 709 if ( aMediaDescriptor.has( "SalvagedFile" ) ) 710 { 711 OUString sSalvagedFile( aMediaDescriptor.getOrDefault( "SalvagedFile", OUString() ) ); 712 // If SalvagedFile is an empty string, this indicates "the document is being recovered, but i_rDocumentURL already 713 // is the real document URL, not the temporary document location" 714 if ( sSalvagedFile.isEmpty() ) 715 sSalvagedFile = i_rDocumentURL; 716 717 OSL_ENSURE( sSalvagedFile == i_rDocumentURL, "ODatabaseModelImpl::setResource: inconsistency!" ); 718 // nowadays, setResource should only be called with the logical URL of the document 719 } 720 #endif 721 722 m_aMediaDescriptor = stripLoadArguments( aMediaDescriptor ); 723 724 impl_switchToLogicalURL( i_rDocumentURL ); 725 } 726 727 ::comphelper::NamedValueCollection ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ) 728 { 729 OSL_ENSURE( !_rArguments.has( "Model" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (1)!" ); 730 OSL_ENSURE( !_rArguments.has( "ViewName" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (2)!" ); 731 732 ::comphelper::NamedValueCollection aMutableArgs( _rArguments ); 733 aMutableArgs.remove( "Model" ); 734 aMutableArgs.remove( "ViewName" ); 735 return aMutableArgs; 736 } 737 738 void ODatabaseModelImpl::disposeStorages() 739 { 740 getDocumentStorageAccess()->disposeStorages(); 741 } 742 743 Reference< XSingleServiceFactory > ODatabaseModelImpl::createStorageFactory() const 744 { 745 return StorageFactory::create( m_aContext ); 746 } 747 748 void ODatabaseModelImpl::commitRootStorage() 749 { 750 Reference< XStorage > xStorage( getOrCreateRootStorage() ); 751 bool bSuccess = commitStorageIfWriteable_ignoreErrors( xStorage ); 752 SAL_WARN_IF(!bSuccess && xStorage.is(), "dbaccess", 753 "ODatabaseModelImpl::commitRootStorage: could not commit the storage!"); 754 } 755 756 Reference< XStorage > const & ODatabaseModelImpl::getOrCreateRootStorage() 757 { 758 if ( !m_xDocumentStorage.is() ) 759 { 760 Reference< XSingleServiceFactory> xStorageFactory = StorageFactory::create( m_aContext ); 761 Any aSource; 762 aSource = m_aMediaDescriptor.get( "Stream" ); 763 if ( !aSource.hasValue() ) 764 aSource = m_aMediaDescriptor.get( "InputStream" ); 765 if ( !aSource.hasValue() && !m_sDocFileLocation.isEmpty() ) 766 aSource <<= m_sDocFileLocation; 767 // TODO: shouldn't we also check URL? 768 769 OSL_ENSURE( aSource.hasValue(), "ODatabaseModelImpl::getOrCreateRootStorage: no source to create the storage from!" ); 770 771 if ( aSource.hasValue() ) 772 { 773 Sequence< Any > aStorageCreationArgs(2); 774 aStorageCreationArgs[0] = aSource; 775 aStorageCreationArgs[1] <<= ElementModes::READWRITE; 776 777 Reference< XStorage > xDocumentStorage; 778 OUString sURL; 779 aSource >>= sURL; 780 // Don't try to load a meta-URL as-is. 781 if (!sURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:")) 782 { 783 try 784 { 785 xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW ); 786 } 787 catch( const Exception& ) 788 { 789 m_bDocumentReadOnly = true; 790 aStorageCreationArgs[1] <<= ElementModes::READ; 791 try 792 { 793 xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW ); 794 } 795 catch( const Exception& ) 796 { 797 DBG_UNHANDLED_EXCEPTION("dbaccess"); 798 } 799 } 800 } 801 802 impl_switchToStorage_throw( xDocumentStorage ); 803 } 804 } 805 return m_xDocumentStorage.getTyped(); 806 } 807 808 DocumentStorageAccess* ODatabaseModelImpl::getDocumentStorageAccess() 809 { 810 if ( !m_pStorageAccess.is() ) 811 { 812 m_pStorageAccess = new DocumentStorageAccess( *this ); 813 } 814 return m_pStorageAccess.get(); 815 } 816 817 void ODatabaseModelImpl::modelIsDisposing( const bool _wasInitialized, ResetModelAccess ) 818 { 819 m_xModel.clear(); 820 821 // Basic libraries and Dialog libraries are a model facet, though held at this impl class. 822 // They automatically dispose themself when the model they belong to is being disposed. 823 // So, to not be tempted to do anything with them, again, we reset them. 824 m_xBasicLibraries.clear(); 825 m_xDialogLibraries.clear(); 826 827 m_bDocumentInitialized = _wasInitialized; 828 } 829 830 Reference< XDocumentSubStorageSupplier > ODatabaseModelImpl::getDocumentSubStorageSupplier() 831 { 832 return getDocumentStorageAccess(); 833 } 834 835 bool ODatabaseModelImpl::commitEmbeddedStorage( bool _bPreventRootCommits ) 836 { 837 return getDocumentStorageAccess()->commitEmbeddedStorage( _bPreventRootCommits ); 838 } 839 840 bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< XStorage >& _rxStorage ) 841 { 842 bool bSuccess = false; 843 try 844 { 845 bSuccess = tools::stor::commitStorageIfWriteable( _rxStorage ); 846 } 847 catch( const Exception& ) 848 { 849 DBG_UNHANDLED_EXCEPTION("dbaccess"); 850 } 851 return bSuccess; 852 } 853 854 void ODatabaseModelImpl::setModified( bool _bModified ) 855 { 856 if ( isModifyLocked() ) 857 return; 858 859 try 860 { 861 Reference< XModifiable > xModi( m_xModel.get(), UNO_QUERY ); 862 if ( xModi.is() ) 863 xModi->setModified( _bModified ); 864 else 865 m_bModified = _bModified; 866 } 867 catch( const Exception& ) 868 { 869 DBG_UNHANDLED_EXCEPTION("dbaccess"); 870 } 871 } 872 873 Reference<XDataSource> ODatabaseModelImpl::getOrCreateDataSource() 874 { 875 Reference<XDataSource> xDs = m_xDataSource; 876 if ( !xDs.is() ) 877 { 878 xDs = new ODatabaseSource(this); 879 m_xDataSource = xDs; 880 } 881 return xDs; 882 } 883 884 Reference< XModel> ODatabaseModelImpl::getModel_noCreate() const 885 { 886 return m_xModel; 887 } 888 889 Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership() 890 { 891 Reference< XModel > xModel( m_xModel ); 892 OSL_PRECOND( !xModel.is(), "ODatabaseModelImpl::createNewModel_deliverOwnership: not to be called if there already is a model!" ); 893 if ( !xModel.is() ) 894 { 895 bool bHadModelBefore = m_bDocumentInitialized; 896 897 xModel = ODatabaseDocument::createDatabaseDocument( this, ODatabaseDocument::FactoryAccess() ); 898 m_xModel = xModel; 899 900 try 901 { 902 Reference< XGlobalEventBroadcaster > xModelCollection = theGlobalEventBroadcaster::get( m_aContext ); 903 xModelCollection->insert( makeAny( xModel ) ); 904 } 905 catch( const Exception& ) 906 { 907 DBG_UNHANDLED_EXCEPTION("dbaccess"); 908 } 909 910 if ( bHadModelBefore ) 911 { 912 // do an attachResources 913 // In case the document is loaded regularly, this is not necessary, as our loader will do it. 914 // However, in case that the document is implicitly created by asking the data source for the document, 915 // then nobody would call the doc's attachResource. So, we do it here, to ensure it's in a proper 916 // state, fires all events, and so on. 917 // #i105505# 918 xModel->attachResource( xModel->getURL(), m_aMediaDescriptor.getPropertyValues() ); 919 } 920 } 921 return xModel; 922 } 923 924 void ODatabaseModelImpl::acquire() 925 { 926 osl_atomic_increment(&m_refCount); 927 } 928 929 void ODatabaseModelImpl::release() 930 { 931 if ( osl_atomic_decrement(&m_refCount) == 0 ) 932 { 933 acquire(); // prevent multiple releases 934 m_rDBContext.removeFromTerminateListener(*this); 935 dispose(); 936 m_rDBContext.storeTransientProperties(*this); 937 if (!m_sDocumentURL.isEmpty()) 938 m_rDBContext.revokeDatabaseDocument(*this); 939 delete this; 940 } 941 } 942 943 void ODatabaseModelImpl::commitStorages() 944 { 945 getDocumentStorageAccess()->commitStorages(); 946 } 947 948 Reference< XStorage > ODatabaseModelImpl::getStorage( const ObjectType _eType ) 949 { 950 return getDocumentStorageAccess()->getDocumentSubStorage( getObjectContainerStorageName( _eType ), 951 css::embed::ElementModes::READWRITE ); 952 } 953 954 const AsciiPropertyValue* ODatabaseModelImpl::getDefaultDataSourceSettings() 955 { 956 static const AsciiPropertyValue aKnownSettings[] = 957 { 958 // known JDBC settings 959 AsciiPropertyValue( "JavaDriverClass", makeAny( OUString() ) ), 960 AsciiPropertyValue( "JavaDriverClassPath", makeAny( OUString() ) ), 961 AsciiPropertyValue( "IgnoreCurrency", makeAny( false ) ), 962 // known settings for file-based drivers 963 AsciiPropertyValue( "Extension", makeAny( OUString() ) ), 964 AsciiPropertyValue( "CharSet", makeAny( OUString() ) ), 965 AsciiPropertyValue( "HeaderLine", makeAny( true ) ), 966 AsciiPropertyValue( "FieldDelimiter", makeAny( OUString( "," ) ) ), 967 AsciiPropertyValue( "StringDelimiter", makeAny( OUString( "\"" ) ) ), 968 AsciiPropertyValue( "DecimalDelimiter", makeAny( OUString( "." ) ) ), 969 AsciiPropertyValue( "ThousandDelimiter", makeAny( OUString() ) ), 970 AsciiPropertyValue( "ShowDeleted", makeAny( false ) ), 971 // known ODBC settings 972 AsciiPropertyValue( "SystemDriverSettings", makeAny( OUString() ) ), 973 AsciiPropertyValue( "UseCatalog", makeAny( false ) ), 974 AsciiPropertyValue( "TypeInfoSettings", makeAny( Sequence< Any >()) ), 975 // settings related to auto increment handling 976 AsciiPropertyValue( "AutoIncrementCreation", makeAny( OUString() ) ), 977 AsciiPropertyValue( "AutoRetrievingStatement", makeAny( OUString() ) ), 978 AsciiPropertyValue( "IsAutoRetrievingEnabled", makeAny( false ) ), 979 // known LDAP driver settings 980 AsciiPropertyValue( "HostName", makeAny( OUString() ) ), 981 AsciiPropertyValue( "PortNumber", makeAny( sal_Int32(389) ) ), 982 AsciiPropertyValue( "BaseDN", makeAny( OUString() ) ), 983 AsciiPropertyValue( "MaxRowCount", makeAny( sal_Int32(100) ) ), 984 // known MySQLNative driver settings 985 AsciiPropertyValue( "LocalSocket", makeAny( OUString() ) ), 986 AsciiPropertyValue( "NamedPipe", makeAny( OUString() ) ), 987 // misc known driver settings 988 AsciiPropertyValue( "ParameterNameSubstitution", makeAny( false ) ), 989 AsciiPropertyValue( "AddIndexAppendix", makeAny( true ) ), 990 AsciiPropertyValue( "IgnoreDriverPrivileges", makeAny( true ) ), 991 AsciiPropertyValue( "ImplicitCatalogRestriction", ::cppu::UnoType< OUString >::get() ), 992 AsciiPropertyValue( "ImplicitSchemaRestriction", ::cppu::UnoType< OUString >::get() ), 993 AsciiPropertyValue( "PrimaryKeySupport", ::cppu::UnoType< sal_Bool >::get() ), 994 AsciiPropertyValue( "ShowColumnDescription", makeAny( false ) ), 995 // known SDB level settings 996 AsciiPropertyValue( "NoNameLengthLimit", makeAny( false ) ), 997 AsciiPropertyValue( "AppendTableAliasName", makeAny( false ) ), 998 AsciiPropertyValue( "GenerateASBeforeCorrelationName", makeAny( false ) ), 999 AsciiPropertyValue( "ColumnAliasInOrderBy", makeAny( true ) ), 1000 AsciiPropertyValue( "EnableSQL92Check", makeAny( false ) ), 1001 AsciiPropertyValue( "BooleanComparisonMode", makeAny( BooleanComparisonMode::EQUAL_INTEGER ) ), 1002 AsciiPropertyValue( "TableTypeFilterMode", makeAny( sal_Int32(3) ) ), 1003 AsciiPropertyValue( "RespectDriverResultSetType", makeAny( false ) ), 1004 AsciiPropertyValue( "UseSchemaInSelect", makeAny( true ) ), 1005 AsciiPropertyValue( "UseCatalogInSelect", makeAny( true ) ), 1006 AsciiPropertyValue( "EnableOuterJoinEscape", makeAny( true ) ), 1007 AsciiPropertyValue( "PreferDosLikeLineEnds", makeAny( false ) ), 1008 AsciiPropertyValue( "FormsCheckRequiredFields", makeAny( true ) ), 1009 AsciiPropertyValue( "EscapeDateTime", makeAny( true ) ), 1010 1011 // known services to handle database tasks 1012 AsciiPropertyValue( "TableAlterationServiceName", makeAny( OUString() ) ), 1013 AsciiPropertyValue( "TableRenameServiceName", makeAny( OUString() ) ), 1014 AsciiPropertyValue( "ViewAlterationServiceName", makeAny( OUString() ) ), 1015 AsciiPropertyValue( "ViewAccessServiceName", makeAny( OUString() ) ), 1016 AsciiPropertyValue( "CommandDefinitions", makeAny( OUString() ) ), 1017 AsciiPropertyValue( "Forms", makeAny( OUString() ) ), 1018 AsciiPropertyValue( "Reports", makeAny( OUString() ) ), 1019 AsciiPropertyValue( "KeyAlterationServiceName", makeAny( OUString() ) ), 1020 AsciiPropertyValue( "IndexAlterationServiceName", makeAny( OUString() ) ), 1021 1022 AsciiPropertyValue() 1023 }; 1024 return aKnownSettings; 1025 } 1026 1027 TContentPtr& ODatabaseModelImpl::getObjectContainer( ObjectType _eType ) 1028 { 1029 OSL_PRECOND( _eType >= E_FORM && _eType <= E_TABLE, "ODatabaseModelImpl::getObjectContainer: illegal index!" ); 1030 TContentPtr& rContentPtr = m_aContainer[ _eType ]; 1031 1032 if ( !rContentPtr.get() ) 1033 { 1034 rContentPtr = TContentPtr( new ODefinitionContainer_Impl ); 1035 rContentPtr->m_pDataSource = this; 1036 rContentPtr->m_aProps.aTitle = lcl_getContainerStorageName_throw( _eType ); 1037 } 1038 return rContentPtr; 1039 } 1040 1041 bool ODatabaseModelImpl::adjustMacroMode_AutoReject() 1042 { 1043 return m_aMacroMode.adjustMacroMode( nullptr ); 1044 } 1045 1046 bool ODatabaseModelImpl::checkMacrosOnLoading() 1047 { 1048 Reference< XInteractionHandler > xInteraction; 1049 xInteraction = m_aMediaDescriptor.getOrDefault( "InteractionHandler", xInteraction ); 1050 return m_aMacroMode.checkMacrosOnLoading( xInteraction ); 1051 } 1052 1053 void ODatabaseModelImpl::resetMacroExecutionMode() 1054 { 1055 m_aMacroMode = ::sfx2::DocumentMacroMode( *this ); 1056 } 1057 1058 Reference< XStorageBasedLibraryContainer > ODatabaseModelImpl::getLibraryContainer( bool _bScript ) 1059 { 1060 Reference< XStorageBasedLibraryContainer >& rxContainer( _bScript ? m_xBasicLibraries : m_xDialogLibraries ); 1061 if ( rxContainer.is() ) 1062 return rxContainer; 1063 1064 Reference< XStorageBasedDocument > xDocument( getModel_noCreate(), UNO_QUERY_THROW ); 1065 // this is only to be called if there already exists a document model - in fact, it is 1066 // to be called by the document model only 1067 1068 try 1069 { 1070 Reference< XStorageBasedLibraryContainer > (*Factory)( const Reference< XComponentContext >&, const Reference< XStorageBasedDocument >&) 1071 = _bScript ? &DocumentScriptLibraryContainer::create : &DocumentDialogLibraryContainer::create; 1072 1073 rxContainer.set( 1074 (*Factory)( m_aContext, xDocument ), 1075 UNO_QUERY_THROW 1076 ); 1077 } 1078 catch( const RuntimeException& ) 1079 { 1080 throw; 1081 } 1082 catch( const Exception& ) 1083 { 1084 throw WrappedTargetRuntimeException( 1085 OUString(), 1086 xDocument, 1087 ::cppu::getCaughtException() 1088 ); 1089 } 1090 return rxContainer; 1091 } 1092 1093 void ODatabaseModelImpl::storeLibraryContainersTo( const Reference< XStorage >& _rxToRootStorage ) 1094 { 1095 if ( m_xBasicLibraries.is() ) 1096 m_xBasicLibraries->storeLibrariesToStorage( _rxToRootStorage ); 1097 1098 if ( m_xDialogLibraries.is() ) 1099 m_xDialogLibraries->storeLibrariesToStorage( _rxToRootStorage ); 1100 } 1101 1102 Reference< XStorage > ODatabaseModelImpl::switchToStorage( const Reference< XStorage >& _rxNewRootStorage ) 1103 { 1104 if ( !_rxNewRootStorage.is() ) 1105 throw IllegalArgumentException(); 1106 1107 return impl_switchToStorage_throw( _rxNewRootStorage ); 1108 } 1109 1110 namespace 1111 { 1112 void lcl_modifyListening( ::sfx2::IModifiableDocument& _rDocument, 1113 const Reference< XStorage >& _rxStorage, ::rtl::Reference< ::sfx2::DocumentStorageModifyListener >& _inout_rListener, 1114 comphelper::SolarMutex& _rMutex, bool _bListen ) 1115 { 1116 Reference< XModifiable > xModify( _rxStorage, UNO_QUERY ); 1117 OSL_ENSURE( xModify.is() || !_rxStorage.is(), "lcl_modifyListening: storage can't notify us!" ); 1118 1119 if ( xModify.is() && !_bListen && _inout_rListener.is() ) 1120 { 1121 xModify->removeModifyListener( _inout_rListener.get() ); 1122 } 1123 1124 if ( _inout_rListener.is() ) 1125 { 1126 _inout_rListener->dispose(); 1127 _inout_rListener = nullptr; 1128 } 1129 1130 if ( xModify.is() && _bListen ) 1131 { 1132 _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument, _rMutex ); 1133 xModify->addModifyListener( _inout_rListener.get() ); 1134 } 1135 } 1136 } 1137 1138 namespace 1139 { 1140 void lcl_rebaseScriptStorage_throw( const Reference< XStorageBasedLibraryContainer >& _rxContainer, 1141 const Reference< XStorage >& _rxNewRootStorage ) 1142 { 1143 if ( _rxContainer.is() ) 1144 { 1145 if ( _rxNewRootStorage.is() ) 1146 _rxContainer->setRootStorage( _rxNewRootStorage ); 1147 // else 1148 // TODO: what to do here? dispose the container? 1149 } 1150 } 1151 } 1152 1153 Reference< XStorage > const & ODatabaseModelImpl::impl_switchToStorage_throw( const Reference< XStorage >& _rxNewRootStorage ) 1154 { 1155 // stop listening for modifications at the old storage 1156 lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, Application::GetSolarMutex(), false ); 1157 1158 // set new storage 1159 m_xDocumentStorage.reset( _rxNewRootStorage, SharedStorage::TakeOwnership ); 1160 1161 // start listening for modifications 1162 lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, Application::GetSolarMutex(), true ); 1163 1164 // forward new storage to Basic and Dialog library containers 1165 lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() ); 1166 lcl_rebaseScriptStorage_throw( m_xDialogLibraries, m_xDocumentStorage.getTyped() ); 1167 1168 m_bReadOnly = !tools::stor::storageIsWritable_nothrow( m_xDocumentStorage.getTyped() ); 1169 // TODO: our data source, if it exists, must broadcast the change of its ReadOnly property 1170 1171 return m_xDocumentStorage.getTyped(); 1172 } 1173 1174 void ODatabaseModelImpl::impl_switchToLogicalURL( const OUString& i_rDocumentURL ) 1175 { 1176 if ( i_rDocumentURL == m_sDocumentURL ) 1177 return; 1178 1179 const OUString sOldURL( m_sDocumentURL ); 1180 // update our name, if necessary 1181 if ( ( m_sName == m_sDocumentURL ) // our name is our old URL 1182 || ( m_sName.isEmpty() ) // we do not have a name, yet (i.e. are not registered at the database context) 1183 ) 1184 { 1185 INetURLObject aURL( i_rDocumentURL ); 1186 if ( aURL.GetProtocol() != INetProtocol::NotValid ) 1187 { 1188 m_sName = i_rDocumentURL; 1189 // TODO: our data source must broadcast the change of the Name property 1190 } 1191 } 1192 1193 // remember URL 1194 m_sDocumentURL = i_rDocumentURL; 1195 1196 // update our location, if necessary 1197 if ( m_sDocFileLocation.isEmpty() ) 1198 m_sDocFileLocation = m_sDocumentURL; 1199 1200 // register at the database context, or change registration 1201 if (!sOldURL.isEmpty()) 1202 m_rDBContext.databaseDocumentURLChange( sOldURL, m_sDocumentURL ); 1203 else 1204 m_rDBContext.registerDatabaseDocument( *this ); 1205 } 1206 1207 OUString ODatabaseModelImpl::getObjectContainerStorageName( const ObjectType _eType ) 1208 { 1209 return lcl_getContainerStorageName_throw( _eType ); 1210 } 1211 1212 sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const 1213 { 1214 sal_Int16 nCurrentMode = MacroExecMode::NEVER_EXECUTE; 1215 try 1216 { 1217 nCurrentMode = m_aMediaDescriptor.getOrDefault( "MacroExecutionMode", nCurrentMode ); 1218 } 1219 catch( const Exception& ) 1220 { 1221 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1222 } 1223 return nCurrentMode; 1224 } 1225 1226 void ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode ) 1227 { 1228 m_aMediaDescriptor.put( "MacroExecutionMode", nMacroMode ); 1229 } 1230 1231 OUString ODatabaseModelImpl::getDocumentLocation() const 1232 { 1233 return getURL(); 1234 // formerly, we returned getDocFileLocation here, which is the location of the file from which we 1235 // recovered the "real" document. 1236 // However, during CWS autorecovery evolving, we clarified (with MAV/MT) the role of XModel::getURL and 1237 // XStorable::getLocation. In this course, we agreed that for a macro security check, the *document URL* 1238 // (not the recovery file URL) is to be used: The recovery file lies in the backup folder, and by definition, 1239 // this folder is considered to be secure. So, the document URL needs to be used to decide about the security. 1240 } 1241 1242 ODatabaseModelImpl::EmbeddedMacros ODatabaseModelImpl::determineEmbeddedMacros() 1243 { 1244 if ( !m_aEmbeddedMacros ) 1245 { 1246 if ( ::sfx2::DocumentMacroMode::storageHasMacros( getOrCreateRootStorage() ) ) 1247 { 1248 m_aEmbeddedMacros.reset( eDocumentWideMacros ); 1249 } 1250 else if ( lcl_hasObjectsWithMacros_nothrow( *this, E_FORM ) 1251 || lcl_hasObjectsWithMacros_nothrow( *this, E_REPORT ) 1252 ) 1253 { 1254 m_aEmbeddedMacros.reset( eSubDocumentMacros ); 1255 } 1256 else 1257 { 1258 m_aEmbeddedMacros.reset( eNoMacros ); 1259 } 1260 } 1261 return *m_aEmbeddedMacros; 1262 } 1263 1264 bool ODatabaseModelImpl::documentStorageHasMacros() const 1265 { 1266 const_cast< ODatabaseModelImpl* >( this )->determineEmbeddedMacros(); 1267 return ( *m_aEmbeddedMacros != eNoMacros ); 1268 } 1269 1270 Reference< XEmbeddedScripts > ODatabaseModelImpl::getEmbeddedDocumentScripts() const 1271 { 1272 return Reference< XEmbeddedScripts >( getModel_noCreate(), UNO_QUERY ); 1273 } 1274 1275 SignatureState ODatabaseModelImpl::getScriptingSignatureState() 1276 { 1277 // no support for signatures at the moment 1278 return SignatureState::NOSIGNATURES; 1279 } 1280 1281 bool ODatabaseModelImpl::hasTrustedScriptingSignature( bool /*bAllowUIToAddAuthor*/ ) 1282 { 1283 // no support for signatures at the moment 1284 return false; 1285 } 1286 1287 void ODatabaseModelImpl::storageIsModified() 1288 { 1289 setModified( true ); 1290 } 1291 1292 ModelDependentComponent::ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model ) 1293 :m_pImpl( _model ) 1294 { 1295 } 1296 1297 ModelDependentComponent::~ModelDependentComponent() 1298 { 1299 } 1300 1301 } // namespace dbaccess 1302 1303 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1304
