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 <config_extensions.h> 21 #include <config_folders.h> 22 23 #include <com/sun/star/container/XNameContainer.hpp> 24 #include <com/sun/star/container/XContainer.hpp> 25 #include <com/sun/star/embed/ElementModes.hpp> 26 #include <com/sun/star/embed/XTransactedObject.hpp> 27 #include <com/sun/star/io/IOException.hpp> 28 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 29 #include <com/sun/star/lang/XServiceInfo.hpp> 30 #include <com/sun/star/ucb/ContentCreationException.hpp> 31 #include <com/sun/star/xml/sax/SAXException.hpp> 32 #include <vcl/svapp.hxx> 33 #include <osl/mutex.hxx> 34 #include <vcl/errinf.hxx> 35 #include <rtl/ustring.hxx> 36 #include <rtl/strbuf.hxx> 37 #include <sal/log.hxx> 38 #include <comphelper/getexpandeduri.hxx> 39 #include <comphelper/processfactory.hxx> 40 #include <comphelper/anytostring.hxx> 41 #include <comphelper/sequence.hxx> 42 43 #include <namecont.hxx> 44 #include <basic/basicmanagerrepository.hxx> 45 #include <tools/diagnose_ex.h> 46 #include <tools/urlobj.hxx> 47 #include <unotools/streamwrap.hxx> 48 #include <unotools/pathoptions.hxx> 49 #include <svtools/sfxecode.hxx> 50 #include <svtools/ehdl.hxx> 51 #include <basic/basmgr.hxx> 52 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> 53 #include <com/sun/star/xml/sax/Parser.hpp> 54 #include <com/sun/star/xml/sax/InputSource.hpp> 55 #include <com/sun/star/io/XOutputStream.hpp> 56 #include <com/sun/star/xml/sax/Writer.hpp> 57 #include <com/sun/star/io/XInputStream.hpp> 58 #include <com/sun/star/io/XActiveDataSource.hpp> 59 #include <com/sun/star/beans/XPropertySet.hpp> 60 #include <com/sun/star/uno/DeploymentException.hpp> 61 #include <com/sun/star/lang/DisposedException.hpp> 62 #include <com/sun/star/script/LibraryNotLoadedException.hpp> 63 #include <com/sun/star/script/vba/VBAScriptEventId.hpp> 64 #include <com/sun/star/ucb/SimpleFileAccess.hpp> 65 #include <com/sun/star/util/PathSubstitution.hpp> 66 #include <com/sun/star/deployment/ExtensionManager.hpp> 67 #include <comphelper/storagehelper.hxx> 68 #include <cppuhelper/exc_hlp.hxx> 69 #include <cppuhelper/queryinterface.hxx> 70 #include <cppuhelper/supportsservice.hxx> 71 #include <basic/sbmod.hxx> 72 #include <memory> 73 74 namespace basic 75 { 76 77 using namespace com::sun::star::document; 78 using namespace com::sun::star::container; 79 using namespace com::sun::star::uno; 80 using namespace com::sun::star::lang; 81 using namespace com::sun::star::io; 82 using namespace com::sun::star::ucb; 83 using namespace com::sun::star::script; 84 using namespace com::sun::star::beans; 85 using namespace com::sun::star::xml::sax; 86 using namespace com::sun::star::util; 87 using namespace com::sun::star::task; 88 using namespace com::sun::star::embed; 89 using namespace com::sun::star::frame; 90 using namespace com::sun::star::deployment; 91 using namespace com::sun::star; 92 using namespace cppu; 93 using namespace osl; 94 95 using com::sun::star::uno::Reference; 96 97 // #i34411: Flag for error handling during migration 98 static bool GbMigrationSuppressErrors = false; 99 100 101 // Implementation class NameContainer 102 103 // Methods XElementAccess 104 Type NameContainer::getElementType() 105 { 106 return mType; 107 } 108 109 sal_Bool NameContainer::hasElements() 110 { 111 bool bRet = (mnElementCount > 0); 112 return bRet; 113 } 114 115 // Methods XNameAccess 116 Any NameContainer::getByName( const OUString& aName ) 117 { 118 NameContainerNameMap::iterator aIt = mHashMap.find( aName ); 119 if( aIt == mHashMap.end() ) 120 { 121 throw NoSuchElementException(); 122 } 123 sal_Int32 iHashResult = (*aIt).second; 124 Any aRetAny = mValues[ iHashResult ]; 125 return aRetAny; 126 } 127 128 Sequence< OUString > NameContainer::getElementNames() 129 { 130 return comphelper::containerToSequence(mNames); 131 } 132 133 sal_Bool NameContainer::hasByName( const OUString& aName ) 134 { 135 NameContainerNameMap::iterator aIt = mHashMap.find( aName ); 136 bool bRet = ( aIt != mHashMap.end() ); 137 return bRet; 138 } 139 140 141 // Methods XNameReplace 142 void NameContainer::replaceByName( const OUString& aName, const Any& aElement ) 143 { 144 const Type& aAnyType = aElement.getValueType(); 145 if( mType != aAnyType ) 146 { 147 throw IllegalArgumentException(); 148 } 149 NameContainerNameMap::iterator aIt = mHashMap.find( aName ); 150 if( aIt == mHashMap.end() ) 151 { 152 throw NoSuchElementException(); 153 } 154 sal_Int32 iHashResult = (*aIt).second; 155 Any aOldElement = mValues[ iHashResult ]; 156 mValues[ iHashResult ] = aElement; 157 158 159 // Fire event 160 if( maContainerListeners.getLength() > 0 ) 161 { 162 ContainerEvent aEvent; 163 aEvent.Source = mpxEventSource; 164 aEvent.Accessor <<= aName; 165 aEvent.Element = aElement; 166 aEvent.ReplacedElement = aOldElement; 167 maContainerListeners.notifyEach( &XContainerListener::elementReplaced, aEvent ); 168 } 169 170 /* After the container event has been fired (one listener will update the 171 core Basic manager), fire change event. Listeners can rely on that the 172 Basic source code of the core Basic manager is up-to-date. */ 173 if( maChangesListeners.getLength() > 0 ) 174 { 175 ChangesEvent aEvent; 176 aEvent.Source = mpxEventSource; 177 aEvent.Base <<= aEvent.Source; 178 aEvent.Changes.realloc( 1 ); 179 aEvent.Changes[ 0 ].Accessor <<= aName; 180 aEvent.Changes[ 0 ].Element = aElement; 181 aEvent.Changes[ 0 ].ReplacedElement = aOldElement; 182 maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent ); 183 } 184 } 185 186 void NameContainer::insertCheck(const OUString& aName, const Any& aElement) 187 { 188 NameContainerNameMap::iterator aIt = mHashMap.find(aName); 189 if( aIt != mHashMap.end() ) 190 { 191 throw ElementExistException(); 192 } 193 insertNoCheck(aName, aElement); 194 } 195 196 void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement) 197 { 198 const Type& aAnyType = aElement.getValueType(); 199 if( mType != aAnyType ) 200 { 201 throw IllegalArgumentException(); 202 } 203 204 sal_Int32 nCount = mNames.size(); 205 mNames.push_back( aName ); 206 mValues.push_back( aElement ); 207 208 mHashMap[ aName ] = nCount; 209 mnElementCount++; 210 211 // Fire event 212 if( maContainerListeners.getLength() > 0 ) 213 { 214 ContainerEvent aEvent; 215 aEvent.Source = mpxEventSource; 216 aEvent.Accessor <<= aName; 217 aEvent.Element = aElement; 218 maContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); 219 } 220 221 /* After the container event has been fired (one listener will update the 222 core Basic manager), fire change event. Listeners can rely on that the 223 Basic source code of the core Basic manager is up-to-date. */ 224 if( maChangesListeners.getLength() > 0 ) 225 { 226 ChangesEvent aEvent; 227 aEvent.Source = mpxEventSource; 228 aEvent.Base <<= aEvent.Source; 229 aEvent.Changes.realloc( 1 ); 230 aEvent.Changes[ 0 ].Accessor <<= aName; 231 aEvent.Changes[ 0 ].Element = aElement; 232 maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent ); 233 } 234 } 235 236 // Methods XNameContainer 237 void NameContainer::insertByName( const OUString& aName, const Any& aElement ) 238 { 239 insertCheck(aName, aElement); 240 } 241 242 void NameContainer::removeByName( const OUString& aName ) 243 { 244 NameContainerNameMap::iterator aIt = mHashMap.find( aName ); 245 if( aIt == mHashMap.end() ) 246 { 247 OUString sMessage = "\"" + aName + "\" not found"; 248 throw NoSuchElementException(sMessage); 249 } 250 251 sal_Int32 iHashResult = (*aIt).second; 252 Any aOldElement = mValues[ iHashResult ]; 253 mHashMap.erase( aIt ); 254 sal_Int32 iLast = mNames.size() - 1; 255 if( iLast != iHashResult ) 256 { 257 mNames[ iHashResult ] = mNames[ iLast ]; 258 mValues[ iHashResult ] = mValues[ iLast ]; 259 mHashMap[ mNames[ iHashResult ] ] = iHashResult; 260 } 261 mNames.resize( iLast ); 262 mValues.resize( iLast ); 263 mnElementCount--; 264 265 // Fire event 266 if( maContainerListeners.getLength() > 0 ) 267 { 268 ContainerEvent aEvent; 269 aEvent.Source = mpxEventSource; 270 aEvent.Accessor <<= aName; 271 aEvent.Element = aOldElement; 272 maContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent ); 273 } 274 275 /* After the container event has been fired (one listener will update the 276 core Basic manager), fire change event. Listeners can rely on that the 277 Basic source code of the core Basic manager is up-to-date. */ 278 if( maChangesListeners.getLength() > 0 ) 279 { 280 ChangesEvent aEvent; 281 aEvent.Source = mpxEventSource; 282 aEvent.Base <<= aEvent.Source; 283 aEvent.Changes.realloc( 1 ); 284 aEvent.Changes[ 0 ].Accessor <<= aName; 285 // aEvent.Changes[ 0 ].Element remains empty (meaning "replaced with nothing") 286 aEvent.Changes[ 0 ].ReplacedElement = aOldElement; 287 maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent ); 288 } 289 } 290 291 292 // Methods XContainer 293 void SAL_CALL NameContainer::addContainerListener( const Reference< XContainerListener >& xListener ) 294 { 295 if( !xListener.is() ) 296 { 297 throw RuntimeException("addContainerListener called with null xListener"); 298 } 299 maContainerListeners.addInterface( Reference<XInterface>(xListener, UNO_QUERY) ); 300 } 301 302 void SAL_CALL NameContainer::removeContainerListener( const Reference< XContainerListener >& xListener ) 303 { 304 if( !xListener.is() ) 305 { 306 throw RuntimeException("removeContainerListener called with null xListener"); 307 } 308 maContainerListeners.removeInterface( Reference<XInterface>(xListener, UNO_QUERY) ); 309 } 310 311 // Methods XChangesNotifier 312 void SAL_CALL NameContainer::addChangesListener( const Reference< XChangesListener >& xListener ) 313 { 314 if( !xListener.is() ) 315 { 316 throw RuntimeException("addChangesListener called with null xListener"); 317 } 318 maChangesListeners.addInterface( Reference<XInterface>(xListener, UNO_QUERY) ); 319 } 320 321 void SAL_CALL NameContainer::removeChangesListener( const Reference< XChangesListener >& xListener ) 322 { 323 if( !xListener.is() ) 324 { 325 throw RuntimeException("removeChangesListener called with null xListener"); 326 } 327 maChangesListeners.removeInterface( Reference<XInterface>(xListener, UNO_QUERY) ); 328 } 329 330 331 // ModifiableHelper 332 333 void ModifiableHelper::setModified( bool _bModified ) 334 { 335 if ( _bModified == mbModified ) 336 { 337 return; 338 } 339 mbModified = _bModified; 340 341 if ( m_aModifyListeners.getLength() == 0 ) 342 { 343 return; 344 } 345 EventObject aModifyEvent( m_rEventSource ); 346 m_aModifyListeners.notifyEach( &XModifyListener::modified, aModifyEvent ); 347 } 348 349 350 VBAScriptListenerContainer::VBAScriptListenerContainer( ::osl::Mutex& rMutex ) : 351 VBAScriptListenerContainer_BASE( rMutex ) 352 { 353 } 354 355 bool VBAScriptListenerContainer::implTypedNotify( const Reference< vba::XVBAScriptListener >& rxListener, const vba::VBAScriptEvent& rEvent ) 356 { 357 rxListener->notifyVBAScriptEvent( rEvent ); 358 return true; // notify all other listeners too 359 } 360 361 // Ctor 362 SfxLibraryContainer::SfxLibraryContainer() 363 : SfxLibraryContainer_BASE( m_aMutex ) 364 , maVBAScriptListeners( m_aMutex ) 365 , mnRunningVBAScripts( 0 ) 366 , mbVBACompat( false ) 367 , maModifiable( *this, m_aMutex ) 368 , maNameContainer( new NameContainer(cppu::UnoType<XNameAccess>::get()) ) 369 , mbOldInfoFormat( false ) 370 , mbOasis2OOoFormat( false ) 371 , mpBasMgr( nullptr ) 372 , mbOwnBasMgr( false ) 373 , meInitMode(DEFAULT) 374 { 375 mxContext = comphelper::getProcessComponentContext(); 376 377 mxSFI = ucb::SimpleFileAccess::create( mxContext ); 378 379 mxStringSubstitution = util::PathSubstitution::create( mxContext ); 380 } 381 382 SfxLibraryContainer::~SfxLibraryContainer() 383 { 384 if( mbOwnBasMgr ) 385 { 386 delete mpBasMgr; 387 } 388 } 389 390 void SfxLibraryContainer::enterMethod() 391 { 392 Application::GetSolarMutex().acquire(); 393 if ( rBHelper.bInDispose || rBHelper.bDisposed ) 394 { 395 throw DisposedException( OUString(), *this ); 396 } 397 } 398 399 void SfxLibraryContainer::leaveMethod() 400 { 401 Application::GetSolarMutex().release(); 402 } 403 404 BasicManager* SfxLibraryContainer::getBasicManager() 405 { 406 try 407 { 408 if ( mpBasMgr ) 409 { 410 return mpBasMgr; 411 } 412 Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY ); 413 SAL_WARN_IF( 414 !xDocument.is(), "basic", 415 ("SfxLibraryContainer::getBasicManager: cannot obtain a BasicManager" 416 " without document!")); 417 if ( xDocument.is() ) 418 { 419 mpBasMgr = BasicManagerRepository::getDocumentBasicManager( xDocument ); 420 } 421 } 422 catch (const css::ucb::ContentCreationException& e) 423 { 424 SAL_WARN( "basic", "SfxLibraryContainer::getBasicManager: " << e ); 425 } 426 return mpBasMgr; 427 } 428 429 // Methods XStorageBasedLibraryContainer 430 Reference< XStorage > SAL_CALL SfxLibraryContainer::getRootStorage() 431 { 432 LibraryContainerMethodGuard aGuard( *this ); 433 return mxStorage; 434 } 435 436 void SAL_CALL SfxLibraryContainer::setRootStorage( const Reference< XStorage >& _rxRootStorage ) 437 { 438 LibraryContainerMethodGuard aGuard( *this ); 439 if ( !_rxRootStorage.is() ) 440 { 441 throw IllegalArgumentException(); 442 } 443 mxStorage = _rxRootStorage; 444 onNewRootStorage(); 445 } 446 447 void SAL_CALL SfxLibraryContainer::storeLibrariesToStorage( const Reference< XStorage >& _rxRootStorage ) 448 { 449 LibraryContainerMethodGuard aGuard( *this ); 450 if ( !_rxRootStorage.is() ) 451 { 452 throw IllegalArgumentException(); 453 } 454 try 455 { 456 storeLibraries_Impl( _rxRootStorage, true ); 457 } 458 catch( const Exception& ) 459 { 460 throw WrappedTargetException( OUString(), 461 *this, ::cppu::getCaughtException() ); 462 } 463 } 464 465 466 // Methods XModifiable 467 sal_Bool SfxLibraryContainer::isModified() 468 { 469 LibraryContainerMethodGuard aGuard( *this ); 470 if ( maModifiable.isModified() ) 471 { 472 return true; 473 } 474 // the library container is not modified, go through the libraries and check whether they are modified 475 Sequence< OUString > aNames = maNameContainer->getElementNames(); 476 const OUString* pNames = aNames.getConstArray(); 477 sal_Int32 nNameCount = aNames.getLength(); 478 479 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 480 { 481 OUString aName = pNames[ i ]; 482 try 483 { 484 SfxLibrary* pImplLib = getImplLib( aName ); 485 if( pImplLib->isModified() ) 486 { 487 if ( aName == "Standard" ) 488 { 489 // this is a workaround that has to be implemented because 490 // empty standard library should stay marked as modified 491 // but should not be treated as modified while it is empty 492 if ( pImplLib->hasElements() ) 493 return true; 494 } 495 else 496 { 497 return true; 498 } 499 } 500 } 501 catch(const css::container::NoSuchElementException&) 502 { 503 } 504 } 505 506 return false; 507 } 508 509 void SAL_CALL SfxLibraryContainer::setModified( sal_Bool _bModified ) 510 { 511 LibraryContainerMethodGuard aGuard( *this ); 512 maModifiable.setModified( _bModified ); 513 } 514 515 void SAL_CALL SfxLibraryContainer::addModifyListener( const Reference< XModifyListener >& _rxListener ) 516 { 517 LibraryContainerMethodGuard aGuard( *this ); 518 maModifiable.addModifyListener( _rxListener ); 519 } 520 521 void SAL_CALL SfxLibraryContainer::removeModifyListener( const Reference< XModifyListener >& _rxListener ) 522 { 523 LibraryContainerMethodGuard aGuard( *this ); 524 maModifiable.removeModifyListener( _rxListener ); 525 } 526 527 // Methods XPersistentLibraryContainer 528 Any SAL_CALL SfxLibraryContainer::getRootLocation() 529 { 530 LibraryContainerMethodGuard aGuard( *this ); 531 return Any( getRootStorage() ); 532 } 533 534 OUString SAL_CALL SfxLibraryContainer::getContainerLocationName() 535 { 536 LibraryContainerMethodGuard aGuard( *this ); 537 return maLibrariesDir; 538 } 539 540 void SAL_CALL SfxLibraryContainer::storeLibraries( ) 541 { 542 LibraryContainerMethodGuard aGuard( *this ); 543 try 544 { 545 storeLibraries_Impl( mxStorage, mxStorage.is() ); 546 // we need to store *all* libraries if and only if we are based on a storage: 547 // in this case, storeLibraries_Impl will remove the source storage, after loading 548 // all libraries, so we need to force them to be stored, again 549 } 550 catch( const Exception& ) 551 { 552 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() ); 553 } 554 } 555 556 static void checkAndCopyFileImpl( const INetURLObject& rSourceFolderInetObj, 557 const INetURLObject& rTargetFolderInetObj, 558 const OUString& rCheckFileName, 559 const OUString& rCheckExtension, 560 const Reference< XSimpleFileAccess3 >& xSFI ) 561 { 562 INetURLObject aTargetFolderInetObj( rTargetFolderInetObj ); 563 aTargetFolderInetObj.insertName( rCheckFileName, true, INetURLObject::LAST_SEGMENT, 564 INetURLObject::EncodeMechanism::All ); 565 aTargetFolderInetObj.setExtension( rCheckExtension ); 566 OUString aTargetFile = aTargetFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 567 if( !xSFI->exists( aTargetFile ) ) 568 { 569 INetURLObject aSourceFolderInetObj( rSourceFolderInetObj ); 570 aSourceFolderInetObj.insertName( rCheckFileName, true, INetURLObject::LAST_SEGMENT, 571 INetURLObject::EncodeMechanism::All ); 572 aSourceFolderInetObj.setExtension( rCheckExtension ); 573 OUString aSourceFile = aSourceFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 574 xSFI->copy( aSourceFile, aTargetFile ); 575 } 576 } 577 578 static void createVariableURL( OUString& rStr, const OUString& rLibName, 579 const OUString& rInfoFileName, bool bUser ) 580 { 581 if( bUser ) 582 { 583 rStr = "$(USER)/basic/"; 584 } 585 else 586 { 587 rStr = "$(INST)/" LIBO_SHARE_FOLDER "/basic/"; 588 } 589 rStr += rLibName + "/" + rInfoFileName + ".xlb/"; 590 } 591 592 void SfxLibraryContainer::init( const OUString& rInitialDocumentURL, const uno::Reference< embed::XStorage >& rxInitialStorage ) 593 { 594 // this might be called from within the ctor, and the impl_init might (indirectly) create 595 // an UNO reference to ourself. 596 // Ensure that we're not destroyed while we're in here 597 osl_atomic_increment( &m_refCount ); 598 init_Impl( rInitialDocumentURL, rxInitialStorage ); 599 osl_atomic_decrement( &m_refCount ); 600 } 601 602 void SfxLibraryContainer::init_Impl( const OUString& rInitialDocumentURL, 603 const uno::Reference< embed::XStorage >& rxInitialStorage ) 604 { 605 uno::Reference< embed::XStorage > xStorage = rxInitialStorage; 606 607 maInitialDocumentURL = rInitialDocumentURL; 608 maInfoFileName = OUString::createFromAscii( getInfoFileName() ); 609 maOldInfoFileName = OUString::createFromAscii( getOldInfoFileName() ); 610 maLibElementFileExtension = OUString::createFromAscii( getLibElementFileExtension() ); 611 maLibrariesDir = OUString::createFromAscii( getLibrariesDir() ); 612 613 meInitMode = DEFAULT; 614 INetURLObject aInitUrlInetObj( maInitialDocumentURL ); 615 OUString aInitFileName = aInitUrlInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 616 if( !aInitFileName.isEmpty() ) 617 { 618 // We need a BasicManager to avoid problems 619 StarBASIC* pBas = new StarBASIC(); 620 mpBasMgr = new BasicManager( pBas ); 621 mbOwnBasMgr = true; 622 623 OUString aExtension = aInitUrlInetObj.getExtension(); 624 if( aExtension == "xlc" ) 625 { 626 meInitMode = CONTAINER_INIT_FILE; 627 INetURLObject aLibPathInetObj( aInitUrlInetObj ); 628 aLibPathInetObj.removeSegment(); 629 maLibraryPath = aLibPathInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 630 } 631 else if( aExtension == "xlb" ) 632 { 633 meInitMode = LIBRARY_INIT_FILE; 634 uno::Reference< embed::XStorage > xDummyStor; 635 ::xmlscript::LibDescriptor aLibDesc; 636 implLoadLibraryIndexFile( nullptr, aLibDesc, xDummyStor, aInitFileName ); 637 return; 638 } 639 else 640 { 641 // Decide between old and new document 642 bool bOldStorage = SotStorage::IsOLEStorage( aInitFileName ); 643 if ( bOldStorage ) 644 { 645 meInitMode = OLD_BASIC_STORAGE; 646 importFromOldStorage( aInitFileName ); 647 return; 648 } 649 else 650 { 651 meInitMode = OFFICE_DOCUMENT; 652 try 653 { 654 xStorage = ::comphelper::OStorageHelper::GetStorageFromURL( aInitFileName, embed::ElementModes::READ ); 655 } 656 catch (const uno::Exception& ) 657 { 658 // TODO: error handling 659 } 660 } 661 } 662 } 663 else 664 { 665 // Default paths 666 maLibraryPath = SvtPathOptions().GetBasicPath(); 667 } 668 669 Reference< XParser > xParser = xml::sax::Parser::create(mxContext); 670 671 uno::Reference< io::XInputStream > xInput; 672 673 mxStorage = xStorage; 674 bool bStorage = mxStorage.is(); 675 676 677 // #110009: Scope to force the StorageRefs to be destructed and 678 // so the streams to be closed before the preload operation 679 { 680 681 uno::Reference< embed::XStorage > xLibrariesStor; 682 OUString aFileName; 683 684 int nPassCount = 1; 685 if( !bStorage && meInitMode == DEFAULT ) 686 { 687 nPassCount = 2; 688 } 689 for( int nPass = 0 ; nPass < nPassCount ; nPass++ ) 690 { 691 if( bStorage ) 692 { 693 SAL_WARN_IF( 694 meInitMode != DEFAULT && meInitMode != OFFICE_DOCUMENT, "basic", 695 "Wrong InitMode for document"); 696 try 697 { 698 uno::Reference< io::XStream > xStream; 699 xLibrariesStor = xStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); 700 701 if ( xLibrariesStor.is() ) 702 { 703 aFileName = maInfoFileName + "-lc.xml"; 704 try 705 { 706 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ ); 707 } 708 catch(const uno::Exception& ) 709 {} 710 711 if( !xStream.is() ) 712 { 713 mbOldInfoFormat = true; 714 715 // Check old version 716 aFileName = maOldInfoFileName + ".xml"; 717 try 718 { 719 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ ); 720 } 721 catch(const uno::Exception& ) 722 {} 723 724 if( !xStream.is() ) 725 { 726 // Check for EA2 document version with wrong extensions 727 aFileName = maOldInfoFileName + ".xli"; 728 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ ); 729 } 730 } 731 } 732 733 if ( xStream.is() ) 734 { 735 xInput = xStream->getInputStream(); 736 } 737 } 738 catch(const uno::Exception& ) 739 { 740 // TODO: error handling? 741 } 742 } 743 else 744 { 745 std::unique_ptr<INetURLObject> pLibInfoInetObj; 746 if( meInitMode == CONTAINER_INIT_FILE ) 747 { 748 aFileName = aInitFileName; 749 } 750 else 751 { 752 if( nPass == 1 ) 753 { 754 pLibInfoInetObj.reset(new INetURLObject( maLibraryPath.getToken(0, ';') )); 755 } 756 else 757 { 758 pLibInfoInetObj.reset(new INetURLObject( maLibraryPath.getToken(1, ';') )); 759 } 760 pLibInfoInetObj->insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 761 pLibInfoInetObj->setExtension( "xlc" ); 762 aFileName = pLibInfoInetObj->GetMainURL( INetURLObject::DecodeMechanism::NONE ); 763 } 764 765 try 766 { 767 xInput = mxSFI->openFileRead( aFileName ); 768 } 769 catch(const Exception& ) 770 { 771 // Silently tolerate empty or missing files 772 xInput.clear(); 773 } 774 775 // Old variant? 776 if( !xInput.is() && nPass == 0 ) 777 { 778 INetURLObject aLibInfoInetObj( maLibraryPath.getToken(1, ';') ); 779 aLibInfoInetObj.insertName( maOldInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 780 aLibInfoInetObj.setExtension( "xli" ); 781 aFileName = aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 782 783 try 784 { 785 xInput = mxSFI->openFileRead( aFileName ); 786 mbOldInfoFormat = true; 787 } 788 catch(const Exception& ) 789 { 790 xInput.clear(); 791 } 792 } 793 } 794 795 if( xInput.is() ) 796 { 797 InputSource source; 798 source.aInputStream = xInput; 799 source.sSystemId = aFileName; 800 801 // start parsing 802 std::unique_ptr< ::xmlscript::LibDescriptorArray> pLibArray(new ::xmlscript::LibDescriptorArray()); 803 804 try 805 { 806 xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( pLibArray.get() ) ); 807 xParser->parseStream( source ); 808 } 809 catch ( const xml::sax::SAXException& e ) 810 { 811 SAL_WARN("basic", e); 812 return; 813 } 814 catch ( const io::IOException& e ) 815 { 816 SAL_WARN("basic", e); 817 return; 818 } 819 820 sal_Int32 nLibCount = pLibArray->mnLibCount; 821 for( sal_Int32 i = 0 ; i < nLibCount ; i++ ) 822 { 823 ::xmlscript::LibDescriptor& rLib = pLibArray->mpLibs[i]; 824 825 // Check storage URL 826 OUString aStorageURL = rLib.aStorageURL; 827 if( !bStorage && aStorageURL.isEmpty() && nPass == 0 ) 828 { 829 OUString aLibraryPath; 830 if( meInitMode == CONTAINER_INIT_FILE ) 831 { 832 aLibraryPath = maLibraryPath; 833 } 834 else 835 { 836 aLibraryPath = maLibraryPath.getToken(1, ';'); 837 } 838 INetURLObject aInetObj( aLibraryPath ); 839 840 aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT, 841 INetURLObject::EncodeMechanism::All ); 842 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 843 if( mxSFI->isFolder( aLibDirPath ) ) 844 { 845 createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, true ); 846 maModifiable.setModified( true ); 847 } 848 else if( rLib.bLink ) 849 { 850 // Check "share" path 851 INetURLObject aShareInetObj( maLibraryPath.getToken(0, ';') ); 852 aShareInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT, 853 INetURLObject::EncodeMechanism::All ); 854 OUString aShareLibDirPath = aShareInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 855 if( mxSFI->isFolder( aShareLibDirPath ) ) 856 { 857 createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, false ); 858 maModifiable.setModified( true ); 859 } 860 else 861 { 862 // #i25537: Ignore lib if library folder does not really exist 863 continue; 864 } 865 } 866 } 867 868 OUString aLibName = rLib.aName; 869 870 // If the same library name is used by the shared and the 871 // user lib container index files the user file wins 872 if( nPass == 1 && hasByName( aLibName ) ) 873 { 874 continue; 875 } 876 SfxLibrary* pImplLib; 877 if( rLib.bLink ) 878 { 879 Reference< XNameAccess > xLib = 880 createLibraryLink( aLibName, rLib.aStorageURL, rLib.bReadOnly ); 881 pImplLib = static_cast< SfxLibrary* >( xLib.get() ); 882 } 883 else 884 { 885 Reference< XNameContainer > xLib = createLibrary( aLibName ); 886 pImplLib = static_cast< SfxLibrary* >( xLib.get() ); 887 pImplLib->mbLoaded = false; 888 pImplLib->mbReadOnly = rLib.bReadOnly; 889 if( !bStorage ) 890 { 891 checkStorageURL( rLib.aStorageURL, pImplLib->maLibInfoFileURL, 892 pImplLib->maStorageURL, pImplLib->maUnexpandedStorageURL ); 893 } 894 } 895 maModifiable.setModified( false ); 896 897 // Read library info files 898 if( !mbOldInfoFormat ) 899 { 900 uno::Reference< embed::XStorage > xLibraryStor; 901 if( !pImplLib->mbInitialised && bStorage ) 902 { 903 try 904 { 905 xLibraryStor = xLibrariesStor->openStorageElement( rLib.aName, 906 embed::ElementModes::READ ); 907 } 908 catch(const uno::Exception& ) 909 { 910 #if OSL_DEBUG_LEVEL > 0 911 Any aError( ::cppu::getCaughtException() ); 912 SAL_WARN( 913 "basic", 914 "couldn't open sub storage for library \"" 915 << rLib.aName << "\". Exception: " 916 << comphelper::anyToString(aError)); 917 #endif 918 } 919 } 920 921 // Link is already initialised in createLibraryLink() 922 if( !pImplLib->mbInitialised && (!bStorage || xLibraryStor.is()) ) 923 { 924 bool bLoaded = implLoadLibraryIndexFile( pImplLib, rLib, xLibraryStor, OUString() ); 925 SAL_WARN_IF( 926 bLoaded && aLibName != rLib.aName, "basic", 927 ("Different library names in library container and" 928 " library info files!")); 929 if( GbMigrationSuppressErrors && !bLoaded ) 930 { 931 removeLibrary( aLibName ); 932 } 933 } 934 } 935 else if( !bStorage ) 936 { 937 // Write new index file immediately because otherwise 938 // the library elements will be lost when storing into 939 // the new info format 940 uno::Reference< embed::XStorage > xTmpStorage; 941 implStoreLibraryIndexFile( pImplLib, rLib, xTmpStorage ); 942 } 943 944 implImportLibDescriptor( pImplLib, rLib ); 945 946 if( nPass == 1 ) 947 { 948 pImplLib->mbSharedIndexFile = true; 949 pImplLib->mbReadOnly = true; 950 } 951 } 952 953 // Keep flag for documents to force writing the new index files 954 if( !bStorage ) 955 { 956 mbOldInfoFormat = false; 957 } 958 } 959 } 960 961 // #110009: END Scope to force the StorageRefs to be destructed 962 } 963 964 if( !bStorage && meInitMode == DEFAULT ) 965 { 966 try 967 { 968 implScanExtensions(); 969 } 970 catch(const uno::Exception& ) 971 { 972 // TODO: error handling? 973 SAL_WARN("basic", "Cannot access extensions!"); 974 } 975 } 976 977 // Preload? 978 { 979 Sequence< OUString > aNames = maNameContainer->getElementNames(); 980 const OUString* pNames = aNames.getConstArray(); 981 sal_Int32 nNameCount = aNames.getLength(); 982 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 983 { 984 OUString aName = pNames[ i ]; 985 SfxLibrary* pImplLib = getImplLib( aName ); 986 if( pImplLib->mbPreload ) 987 { 988 loadLibrary( aName ); 989 } 990 } 991 } 992 993 if( meInitMode == DEFAULT ) 994 { 995 INetURLObject aUserBasicInetObj( maLibraryPath.getToken(1, ';') ); 996 OUString aStandardStr("Standard"); 997 998 INetURLObject aPrevUserBasicInetObj_1( aUserBasicInetObj ); 999 aPrevUserBasicInetObj_1.removeSegment(); 1000 INetURLObject aPrevUserBasicInetObj_2 = aPrevUserBasicInetObj_1; 1001 aPrevUserBasicInetObj_1.Append( "__basic_80" ); 1002 aPrevUserBasicInetObj_2.Append( "__basic_80_2" ); 1003 1004 // #i93163 1005 bool bCleanUp = false; 1006 try 1007 { 1008 INetURLObject aPrevUserBasicInetObj = aPrevUserBasicInetObj_1; 1009 OUString aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1010 if( mxSFI->isFolder( aPrevFolder ) ) 1011 { 1012 // Check if Standard folder exists and is complete 1013 INetURLObject aUserBasicStandardInetObj( aUserBasicInetObj ); 1014 aUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT, 1015 INetURLObject::EncodeMechanism::All ); 1016 INetURLObject aPrevUserBasicStandardInetObj( aPrevUserBasicInetObj ); 1017 aPrevUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT, 1018 INetURLObject::EncodeMechanism::All ); 1019 OUString aPrevStandardFolder = aPrevUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1020 if( mxSFI->isFolder( aPrevStandardFolder ) ) 1021 { 1022 OUString aXlbExtension( "xlb" ); 1023 OUString aCheckFileName; 1024 1025 // Check if script.xlb exists 1026 aCheckFileName = "script"; 1027 checkAndCopyFileImpl( aUserBasicStandardInetObj, 1028 aPrevUserBasicStandardInetObj, 1029 aCheckFileName, aXlbExtension, mxSFI ); 1030 1031 // Check if dialog.xlb exists 1032 aCheckFileName = "dialog"; 1033 checkAndCopyFileImpl( aUserBasicStandardInetObj, 1034 aPrevUserBasicStandardInetObj, 1035 aCheckFileName, aXlbExtension, mxSFI ); 1036 1037 // Check if module1.xba exists 1038 aCheckFileName = "Module1"; 1039 checkAndCopyFileImpl( aUserBasicStandardInetObj, 1040 aPrevUserBasicStandardInetObj, 1041 aCheckFileName, "xba", mxSFI ); 1042 } 1043 else 1044 { 1045 OUString aStandardFolder = aUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1046 mxSFI->copy( aStandardFolder, aPrevStandardFolder ); 1047 } 1048 1049 OUString aPrevCopyToFolder = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1050 mxSFI->copy( aPrevFolder, aPrevCopyToFolder ); 1051 } 1052 else 1053 { 1054 aPrevUserBasicInetObj = aPrevUserBasicInetObj_2; 1055 aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1056 } 1057 if( mxSFI->isFolder( aPrevFolder ) ) 1058 { 1059 rtl::Reference<SfxLibraryContainer> pPrevCont = createInstanceImpl(); 1060 1061 // Rename previous basic folder to make storage URLs correct during initialisation 1062 OUString aFolderUserBasic = aUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1063 INetURLObject aUserBasicTmpInetObj( aUserBasicInetObj ); 1064 aUserBasicTmpInetObj.removeSegment(); 1065 aUserBasicTmpInetObj.Append( "__basic_tmp" ); 1066 OUString aFolderTmp = aUserBasicTmpInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1067 1068 mxSFI->move( aFolderUserBasic, aFolderTmp ); 1069 try 1070 { 1071 mxSFI->move( aPrevFolder, aFolderUserBasic ); 1072 } 1073 catch(const Exception& ) 1074 { 1075 // Move back user/basic folder 1076 try 1077 { 1078 mxSFI->kill( aFolderUserBasic ); 1079 } 1080 catch(const Exception& ) 1081 {} 1082 mxSFI->move( aFolderTmp, aFolderUserBasic ); 1083 throw; 1084 } 1085 1086 INetURLObject aPrevUserBasicLibInfoInetObj( aUserBasicInetObj ); 1087 aPrevUserBasicLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, 1088 INetURLObject::EncodeMechanism::All ); 1089 aPrevUserBasicLibInfoInetObj.setExtension( "xlc"); 1090 OUString aLibInfoFileName = aPrevUserBasicLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1091 Sequence<Any> aInitSeq( 1 ); 1092 aInitSeq.getArray()[0] <<= aLibInfoFileName; 1093 GbMigrationSuppressErrors = true; 1094 pPrevCont->initialize( aInitSeq ); 1095 GbMigrationSuppressErrors = false; 1096 1097 // Rename folders back 1098 mxSFI->move( aFolderUserBasic, aPrevFolder ); 1099 mxSFI->move( aFolderTmp, aFolderUserBasic ); 1100 1101 Sequence< OUString > aNames = pPrevCont->getElementNames(); 1102 const OUString* pNames = aNames.getConstArray(); 1103 sal_Int32 nNameCount = aNames.getLength(); 1104 1105 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 1106 { 1107 OUString aLibName = pNames[ i ]; 1108 if( hasByName( aLibName ) ) 1109 { 1110 if( aLibName == aStandardStr ) 1111 { 1112 SfxLibrary* pImplLib = getImplLib( aStandardStr ); 1113 OUString aStandardFolder = pImplLib->maStorageURL; 1114 mxSFI->kill( aStandardFolder ); 1115 } 1116 else 1117 { 1118 continue; 1119 } 1120 } 1121 1122 SfxLibrary* pImplLib = pPrevCont->getImplLib( aLibName ); 1123 if( pImplLib->mbLink ) 1124 { 1125 OUString aStorageURL = pImplLib->maUnexpandedStorageURL; 1126 bool bCreateLink = true; 1127 if( aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 || 1128 aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1 || 1129 aStorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 || 1130 aStorageURL.indexOf( "$(INST)" ) != -1 ) 1131 { 1132 bCreateLink = false; 1133 } 1134 if( bCreateLink ) 1135 { 1136 createLibraryLink( aLibName, pImplLib->maStorageURL, pImplLib->mbReadOnly ); 1137 } 1138 } 1139 else 1140 { 1141 // Move folder if not already done 1142 INetURLObject aUserBasicLibFolderInetObj( aUserBasicInetObj ); 1143 aUserBasicLibFolderInetObj.Append( aLibName ); 1144 OUString aLibFolder = aUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1145 1146 INetURLObject aPrevUserBasicLibFolderInetObj( aPrevUserBasicInetObj ); 1147 aPrevUserBasicLibFolderInetObj.Append( aLibName ); 1148 OUString aPrevLibFolder = aPrevUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1149 1150 if( mxSFI->isFolder( aPrevLibFolder ) && !mxSFI->isFolder( aLibFolder ) ) 1151 { 1152 mxSFI->move( aPrevLibFolder, aLibFolder ); 1153 } 1154 1155 if( aLibName == aStandardStr ) 1156 { 1157 maNameContainer->removeByName( aLibName ); 1158 } 1159 1160 // Create library 1161 Reference< XNameContainer > xLib = createLibrary( aLibName ); 1162 SfxLibrary* pNewLib = static_cast< SfxLibrary* >( xLib.get() ); 1163 pNewLib->mbLoaded = false; 1164 pNewLib->implSetModified( false ); 1165 checkStorageURL( aLibFolder, pNewLib->maLibInfoFileURL, 1166 pNewLib->maStorageURL, pNewLib->maUnexpandedStorageURL ); 1167 1168 uno::Reference< embed::XStorage > xDummyStor; 1169 ::xmlscript::LibDescriptor aLibDesc; 1170 implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, pNewLib->maLibInfoFileURL ); 1171 implImportLibDescriptor( pNewLib, aLibDesc ); 1172 } 1173 } 1174 mxSFI->kill( aPrevFolder ); 1175 } 1176 } 1177 catch(const Exception& e) 1178 { 1179 bCleanUp = true; 1180 SAL_WARN("basic", "Upgrade of Basic installation failed somehow: " << e); 1181 } 1182 1183 // #i93163 1184 if( bCleanUp ) 1185 { 1186 INetURLObject aPrevUserBasicInetObj_Err( aUserBasicInetObj ); 1187 aPrevUserBasicInetObj_Err.removeSegment(); 1188 aPrevUserBasicInetObj_Err.Append( "__basic_80_err" ); 1189 OUString aPrevFolder_Err = aPrevUserBasicInetObj_Err.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1190 1191 bool bSaved = false; 1192 try 1193 { 1194 OUString aPrevFolder_1 = aPrevUserBasicInetObj_1.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1195 if( mxSFI->isFolder( aPrevFolder_1 ) ) 1196 { 1197 mxSFI->move( aPrevFolder_1, aPrevFolder_Err ); 1198 bSaved = true; 1199 } 1200 } 1201 catch(const Exception& ) 1202 {} 1203 try 1204 { 1205 OUString aPrevFolder_2 = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1206 if( !bSaved && mxSFI->isFolder( aPrevFolder_2 ) ) 1207 { 1208 mxSFI->move( aPrevFolder_2, aPrevFolder_Err ); 1209 } 1210 else 1211 { 1212 mxSFI->kill( aPrevFolder_2 ); 1213 } 1214 } 1215 catch(const Exception& ) 1216 {} 1217 } 1218 } 1219 } 1220 1221 void SfxLibraryContainer::implScanExtensions() 1222 { 1223 #if HAVE_FEATURE_EXTENSIONS 1224 ScriptExtensionIterator aScriptIt; 1225 OUString aLibURL; 1226 1227 bool bPureDialogLib = false; 1228 while ( !(aLibURL = aScriptIt.nextBasicOrDialogLibrary( bPureDialogLib )).isEmpty()) 1229 { 1230 if( bPureDialogLib && maInfoFileName == "script" ) 1231 { 1232 continue; 1233 } 1234 // Extract lib name 1235 sal_Int32 nLen = aLibURL.getLength(); 1236 sal_Int32 indexLastSlash = aLibURL.lastIndexOf( '/' ); 1237 sal_Int32 nReduceCopy = 0; 1238 if( indexLastSlash == nLen - 1 ) 1239 { 1240 nReduceCopy = 1; 1241 indexLastSlash = aLibURL.lastIndexOf( '/', nLen - 1 ); 1242 } 1243 1244 OUString aLibName = aLibURL.copy( indexLastSlash + 1, nLen - indexLastSlash - nReduceCopy - 1 ); 1245 1246 // If a library of the same exists the existing library wins 1247 if( hasByName( aLibName ) ) 1248 { 1249 continue; 1250 } 1251 // Add index file to URL 1252 OUString aIndexFileURL = aLibURL; 1253 if( nReduceCopy == 0 ) 1254 { 1255 aIndexFileURL += "/"; 1256 } 1257 aIndexFileURL += maInfoFileName + ".xlb"; 1258 1259 // Create link 1260 const bool bReadOnly = false; 1261 createLibraryLink( aLibName, aIndexFileURL, bReadOnly ); 1262 } 1263 #else 1264 (void) this; 1265 #endif 1266 } 1267 1268 // Handle maLibInfoFileURL and maStorageURL correctly 1269 void SfxLibraryContainer::checkStorageURL( const OUString& aSourceURL, 1270 OUString& aLibInfoFileURL, OUString& aStorageURL, 1271 OUString& aUnexpandedStorageURL ) 1272 { 1273 OUString aExpandedSourceURL = expand_url( aSourceURL ); 1274 if( aExpandedSourceURL != aSourceURL ) 1275 { 1276 aUnexpandedStorageURL = aSourceURL; 1277 } 1278 INetURLObject aInetObj( aExpandedSourceURL ); 1279 OUString aExtension = aInetObj.getExtension(); 1280 if( aExtension == "xlb" ) 1281 { 1282 // URL to xlb file 1283 aLibInfoFileURL = aExpandedSourceURL; 1284 aInetObj.removeSegment(); 1285 aStorageURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1286 } 1287 else 1288 { 1289 // URL to library folder 1290 aStorageURL = aExpandedSourceURL; 1291 aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 1292 aInetObj.setExtension( "xlb" ); 1293 aLibInfoFileURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1294 } 1295 } 1296 1297 SfxLibrary* SfxLibraryContainer::getImplLib( const OUString& rLibraryName ) 1298 { 1299 Any aLibAny = maNameContainer->getByName( rLibraryName ) ; 1300 Reference< XNameAccess > xNameAccess; 1301 aLibAny >>= xNameAccess; 1302 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); 1303 return pImplLib; 1304 } 1305 1306 1307 // Storing with password encryption 1308 1309 // Empty implementation, avoids unnecessary implementation in dlgcont.cxx 1310 bool SfxLibraryContainer::implStorePasswordLibrary( SfxLibrary*, 1311 const OUString&, 1312 const uno::Reference< embed::XStorage >&, 1313 const uno::Reference< task::XInteractionHandler >& ) 1314 { 1315 return false; 1316 } 1317 1318 bool SfxLibraryContainer::implStorePasswordLibrary( 1319 SfxLibrary* /*pLib*/, 1320 const OUString& /*aName*/, 1321 const css::uno::Reference< css::embed::XStorage >& /*xStorage*/, 1322 const OUString& /*aTargetURL*/, 1323 const Reference< XSimpleFileAccess3 >& /*xToUseSFI*/, 1324 const uno::Reference< task::XInteractionHandler >& ) 1325 { 1326 return false; 1327 } 1328 1329 bool SfxLibraryContainer::implLoadPasswordLibrary( 1330 SfxLibrary* /*pLib*/, 1331 const OUString& /*Name*/, 1332 bool /*bVerifyPasswordOnly*/ ) 1333 { 1334 return true; 1335 } 1336 1337 OUString SfxLibraryContainer::createAppLibraryFolder( SfxLibrary* pLib, const OUString& aName ) 1338 { 1339 OUString aLibDirPath = pLib->maStorageURL; 1340 if( aLibDirPath.isEmpty() ) 1341 { 1342 INetURLObject aInetObj( maLibraryPath.getToken(1, ';') ); 1343 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 1344 checkStorageURL( aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), pLib->maLibInfoFileURL, 1345 pLib->maStorageURL, pLib->maUnexpandedStorageURL ); 1346 aLibDirPath = pLib->maStorageURL; 1347 } 1348 1349 if( !mxSFI->isFolder( aLibDirPath ) ) 1350 { 1351 try 1352 { 1353 mxSFI->createFolder( aLibDirPath ); 1354 } 1355 catch(const Exception& ) 1356 {} 1357 } 1358 1359 return aLibDirPath; 1360 } 1361 1362 // Storing 1363 void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib, 1364 const OUString& aName, 1365 const uno::Reference< embed::XStorage >& xStorage ) 1366 { 1367 Reference< XSimpleFileAccess3 > xDummySFA; 1368 Reference< XInteractionHandler > xDummyHandler; 1369 implStoreLibrary( pLib, aName, xStorage, OUString(), xDummySFA, xDummyHandler ); 1370 } 1371 1372 // New variant for library export 1373 void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib, 1374 const OUString& aName, 1375 const uno::Reference< embed::XStorage >& xStorage, 1376 const OUString& aTargetURL, 1377 const Reference< XSimpleFileAccess3 >& rToUseSFI, 1378 const Reference< XInteractionHandler >& xHandler ) 1379 { 1380 bool bLink = pLib->mbLink; 1381 bool bStorage = xStorage.is() && !bLink; 1382 1383 Sequence< OUString > aElementNames = pLib->getElementNames(); 1384 sal_Int32 nNameCount = aElementNames.getLength(); 1385 const OUString* pNames = aElementNames.getConstArray(); 1386 1387 if( bStorage ) 1388 { 1389 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 1390 { 1391 OUString aElementName = pNames[ i ]; 1392 OUString aStreamName = aElementName + ".xml"; 1393 1394 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) ) 1395 { 1396 SAL_WARN( 1397 "basic", 1398 "invalid library element \"" << aElementName << '"'); 1399 continue; 1400 } 1401 try 1402 { 1403 uno::Reference< io::XStream > xElementStream = xStorage->openStreamElement( 1404 aStreamName, 1405 embed::ElementModes::READWRITE ); 1406 // throw uno::RuntimeException(); // TODO: method must either return the stream or throw an exception 1407 1408 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY ); 1409 SAL_WARN_IF( 1410 !xProps.is(), "basic", 1411 "The StorageStream must implement XPropertySet interface!"); 1412 //if ( !xProps.is() ) //TODO 1413 1414 if ( xProps.is() ) 1415 { 1416 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) ); 1417 1418 // #87671 Allow encryption 1419 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) ); 1420 1421 Reference< XOutputStream > xOutput = xElementStream->getOutputStream(); 1422 Reference< XNameContainer > xLib( pLib ); 1423 writeLibraryElement( xLib, aElementName, xOutput ); 1424 } 1425 } 1426 catch(const uno::Exception& ) 1427 { 1428 SAL_WARN("basic", "Problem during storing of library!"); 1429 // TODO: error handling? 1430 } 1431 } 1432 pLib->storeResourcesToStorage( xStorage ); 1433 } 1434 else 1435 { 1436 // Export? 1437 bool bExport = !aTargetURL.isEmpty(); 1438 try 1439 { 1440 Reference< XSimpleFileAccess3 > xSFI = mxSFI; 1441 if( rToUseSFI.is() ) 1442 { 1443 xSFI = rToUseSFI; 1444 } 1445 OUString aLibDirPath; 1446 if( bExport ) 1447 { 1448 INetURLObject aInetObj( aTargetURL ); 1449 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 1450 aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1451 1452 if( !xSFI->isFolder( aLibDirPath ) ) 1453 { 1454 xSFI->createFolder( aLibDirPath ); 1455 } 1456 pLib->storeResourcesToURL( aLibDirPath, xHandler ); 1457 } 1458 else 1459 { 1460 aLibDirPath = createAppLibraryFolder( pLib, aName ); 1461 pLib->storeResources(); 1462 } 1463 1464 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 1465 { 1466 OUString aElementName = pNames[ i ]; 1467 1468 INetURLObject aElementInetObj( aLibDirPath ); 1469 aElementInetObj.insertName( aElementName, false, 1470 INetURLObject::LAST_SEGMENT, 1471 INetURLObject::EncodeMechanism::All ); 1472 aElementInetObj.setExtension( maLibElementFileExtension ); 1473 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); 1474 1475 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) ) 1476 { 1477 SAL_WARN( 1478 "basic", 1479 "invalid library element \"" << aElementName << '"'); 1480 continue; 1481 } 1482 1483 // TODO: Check modified 1484 try 1485 { 1486 if( xSFI->exists( aElementPath ) ) 1487 { 1488 xSFI->kill( aElementPath ); 1489 } 1490 Reference< XOutputStream > xOutput = xSFI->openFileWrite( aElementPath ); 1491 Reference< XNameContainer > xLib( pLib ); 1492 writeLibraryElement( xLib, aElementName, xOutput ); 1493 xOutput->closeOutput(); 1494 } 1495 catch(const Exception& ) 1496 { 1497 if( bExport ) 1498 { 1499 throw; 1500 } 1501 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aElementPath ); 1502 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 1503 } 1504 } 1505 } 1506 catch(const Exception& ) 1507 { 1508 if( bExport ) 1509 { 1510 throw; 1511 } 1512 } 1513 } 1514 } 1515 1516 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib, 1517 const ::xmlscript::LibDescriptor& rLib, 1518 const uno::Reference< embed::XStorage >& xStorage ) 1519 { 1520 Reference< XSimpleFileAccess3 > xDummySFA; 1521 implStoreLibraryIndexFile( pLib, rLib, xStorage, OUString(), xDummySFA ); 1522 } 1523 1524 // New variant for library export 1525 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib, 1526 const ::xmlscript::LibDescriptor& rLib, 1527 const uno::Reference< embed::XStorage >& xStorage, 1528 const OUString& aTargetURL, 1529 const Reference< XSimpleFileAccess3 >& rToUseSFI ) 1530 { 1531 // Create sax writer 1532 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext); 1533 1534 bool bLink = pLib->mbLink; 1535 bool bStorage = xStorage.is() && !bLink; 1536 1537 // Write info file 1538 uno::Reference< io::XOutputStream > xOut; 1539 uno::Reference< io::XStream > xInfoStream; 1540 if( bStorage ) 1541 { 1542 OUString aStreamName = maInfoFileName + "-lb.xml"; 1543 1544 try 1545 { 1546 xInfoStream = xStorage->openStreamElement( aStreamName, embed::ElementModes::READWRITE ); 1547 SAL_WARN_IF(!xInfoStream.is(), "basic", "No stream!"); 1548 uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY ); 1549 // throw uno::RuntimeException(); // TODO 1550 1551 if ( xProps.is() ) 1552 { 1553 xProps->setPropertyValue("MediaType", uno::Any( OUString("text/xml") ) ); 1554 1555 // #87671 Allow encryption 1556 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) ); 1557 1558 xOut = xInfoStream->getOutputStream(); 1559 } 1560 } 1561 catch(const uno::Exception& ) 1562 { 1563 SAL_WARN("basic", "Problem during storing of library index file!"); 1564 // TODO: error handling? 1565 } 1566 } 1567 else 1568 { 1569 // Export? 1570 bool bExport = !aTargetURL.isEmpty(); 1571 Reference< XSimpleFileAccess3 > xSFI = mxSFI; 1572 if( rToUseSFI.is() ) 1573 { 1574 xSFI = rToUseSFI; 1575 } 1576 OUString aLibInfoPath; 1577 if( bExport ) 1578 { 1579 INetURLObject aInetObj( aTargetURL ); 1580 aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 1581 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1582 if( !xSFI->isFolder( aLibDirPath ) ) 1583 { 1584 xSFI->createFolder( aLibDirPath ); 1585 } 1586 aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 1587 aInetObj.setExtension( "xlb" ); 1588 aLibInfoPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1589 } 1590 else 1591 { 1592 createAppLibraryFolder( pLib, rLib.aName ); 1593 aLibInfoPath = pLib->maLibInfoFileURL; 1594 } 1595 1596 try 1597 { 1598 if( xSFI->exists( aLibInfoPath ) ) 1599 { 1600 xSFI->kill( aLibInfoPath ); 1601 } 1602 xOut = xSFI->openFileWrite( aLibInfoPath ); 1603 } 1604 catch(const Exception& ) 1605 { 1606 if( bExport ) 1607 { 1608 throw; 1609 } 1610 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath ); 1611 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 1612 } 1613 } 1614 if( !xOut.is() ) 1615 { 1616 SAL_WARN("basic", "couldn't open output stream"); 1617 return; 1618 } 1619 xWriter->setOutputStream( xOut ); 1620 xmlscript::exportLibrary( xWriter, rLib ); 1621 } 1622 1623 1624 bool SfxLibraryContainer::implLoadLibraryIndexFile( SfxLibrary* pLib, 1625 ::xmlscript::LibDescriptor& rLib, 1626 const uno::Reference< embed::XStorage >& xStorage, 1627 const OUString& aIndexFileName ) 1628 { 1629 Reference< XParser > xParser = xml::sax::Parser::create(mxContext); 1630 1631 bool bStorage = false; 1632 if( pLib ) 1633 { 1634 bool bLink = pLib->mbLink; 1635 bStorage = xStorage.is() && !bLink; 1636 } 1637 1638 // Read info file 1639 uno::Reference< io::XInputStream > xInput; 1640 OUString aLibInfoPath; 1641 if( bStorage ) 1642 { 1643 aLibInfoPath = maInfoFileName + "-lb.xml"; 1644 1645 try 1646 { 1647 uno::Reference< io::XStream > xInfoStream = 1648 xStorage->openStreamElement( aLibInfoPath, embed::ElementModes::READ ); 1649 xInput = xInfoStream->getInputStream(); 1650 } 1651 catch(const uno::Exception& ) 1652 {} 1653 } 1654 else 1655 { 1656 // Create Input stream 1657 //String aLibInfoPath; // attention: THIS PROBLEM MUST BE REVIEWED BY SCRIPTING OWNER!!! 1658 1659 if( pLib ) 1660 { 1661 createAppLibraryFolder( pLib, rLib.aName ); 1662 aLibInfoPath = pLib->maLibInfoFileURL; 1663 } 1664 else 1665 { 1666 aLibInfoPath = aIndexFileName; 1667 } 1668 try 1669 { 1670 xInput = mxSFI->openFileRead( aLibInfoPath ); 1671 } 1672 catch(const Exception& ) 1673 { 1674 xInput.clear(); 1675 if( !GbMigrationSuppressErrors ) 1676 { 1677 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath ); 1678 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 1679 } 1680 } 1681 } 1682 if( !xInput.is() ) 1683 { 1684 return false; 1685 } 1686 1687 InputSource source; 1688 source.aInputStream = xInput; 1689 source.sSystemId = aLibInfoPath; 1690 1691 // start parsing 1692 try 1693 { 1694 xParser->setDocumentHandler( ::xmlscript::importLibrary( rLib ) ); 1695 xParser->parseStream( source ); 1696 } 1697 catch(const Exception& ) 1698 { 1699 SAL_WARN("basic", "Parsing error"); 1700 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath ); 1701 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 1702 return false; 1703 } 1704 1705 if( !pLib ) 1706 { 1707 Reference< XNameContainer > xLib = createLibrary( rLib.aName ); 1708 pLib = static_cast< SfxLibrary* >( xLib.get() ); 1709 pLib->mbLoaded = false; 1710 rLib.aStorageURL = aIndexFileName; 1711 checkStorageURL( rLib.aStorageURL, pLib->maLibInfoFileURL, pLib->maStorageURL, 1712 pLib->maUnexpandedStorageURL ); 1713 1714 implImportLibDescriptor( pLib, rLib ); 1715 } 1716 1717 return true; 1718 } 1719 1720 void SfxLibraryContainer::implImportLibDescriptor( SfxLibrary* pLib, 1721 ::xmlscript::LibDescriptor const & rLib ) 1722 { 1723 if( !pLib->mbInitialised ) 1724 { 1725 sal_Int32 nElementCount = rLib.aElementNames.getLength(); 1726 const OUString* pElementNames = rLib.aElementNames.getConstArray(); 1727 Any aDummyElement = createEmptyLibraryElement(); 1728 for( sal_Int32 i = 0 ; i < nElementCount ; i++ ) 1729 { 1730 pLib->maNameContainer->insertByName( pElementNames[i], aDummyElement ); 1731 } 1732 pLib->mbPasswordProtected = rLib.bPasswordProtected; 1733 pLib->mbReadOnly = rLib.bReadOnly; 1734 pLib->mbPreload = rLib.bPreload; 1735 pLib->implSetModified( false ); 1736 pLib->mbInitialised = true; 1737 } 1738 } 1739 1740 1741 // Methods of new XLibraryStorage interface? 1742 void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference< embed::XStorage >& i_rStorage, 1743 bool bComplete ) 1744 { 1745 const Sequence< OUString > aNames = maNameContainer->getElementNames(); 1746 const sal_Int32 nNameCount = aNames.getLength(); 1747 const OUString* pName = aNames.getConstArray(); 1748 const OUString* pNamesEnd = aNames.getConstArray() + nNameCount; 1749 1750 // Don't count libs from shared index file 1751 sal_Int32 nLibsToSave = nNameCount; 1752 for( ; pName != pNamesEnd; ++pName ) 1753 { 1754 SfxLibrary* pImplLib = getImplLib( *pName ); 1755 if( pImplLib->mbSharedIndexFile || pImplLib->mbExtension ) 1756 { 1757 nLibsToSave--; 1758 } 1759 } 1760 // Write to storage? 1761 bool bStorage = i_rStorage.is(); 1762 uno::Reference< embed::XStorage > xSourceLibrariesStor; 1763 uno::Reference< embed::XStorage > xTargetLibrariesStor; 1764 OUString sTempTargetStorName; 1765 const bool bInplaceStorage = bStorage && ( i_rStorage == mxStorage ); 1766 1767 if( nLibsToSave == 0 ) 1768 { 1769 if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) ) 1770 { 1771 mxStorage->removeElement(maLibrariesDir); 1772 } 1773 return; 1774 } 1775 1776 if ( bStorage ) 1777 { 1778 // Don't write if only empty standard lib exists 1779 if ( ( nLibsToSave == 1 ) && ( aNames[0] == "Standard" ) ) 1780 { 1781 Any aLibAny = maNameContainer->getByName( aNames[0] ); 1782 Reference< XNameAccess > xNameAccess; 1783 aLibAny >>= xNameAccess; 1784 if ( ! xNameAccess->hasElements() ) 1785 { 1786 if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) ) 1787 { 1788 mxStorage->removeElement(maLibrariesDir); 1789 } 1790 return; 1791 } 1792 } 1793 1794 // create the empty target storage 1795 try 1796 { 1797 OUString sTargetLibrariesStoreName; 1798 if ( bInplaceStorage ) 1799 { 1800 // create a temporary target storage 1801 const OUStringBuffer aTempTargetNameBase = maLibrariesDir + "_temp_"; 1802 sal_Int32 index = 0; 1803 do 1804 { 1805 OUStringBuffer aTempTargetName( aTempTargetNameBase ); 1806 aTempTargetName.append( index++ ); 1807 1808 sTargetLibrariesStoreName = aTempTargetName.makeStringAndClear(); 1809 if ( !i_rStorage->hasByName( sTargetLibrariesStoreName ) ) 1810 { 1811 break; 1812 } 1813 } 1814 while ( true ); 1815 sTempTargetStorName = sTargetLibrariesStoreName; 1816 } 1817 else 1818 { 1819 sTargetLibrariesStoreName = maLibrariesDir; 1820 if ( i_rStorage->hasByName( sTargetLibrariesStoreName ) ) 1821 { 1822 i_rStorage->removeElement( sTargetLibrariesStoreName ); 1823 } 1824 } 1825 1826 xTargetLibrariesStor.set( i_rStorage->openStorageElement( sTargetLibrariesStoreName, embed::ElementModes::READWRITE ), UNO_QUERY_THROW ); 1827 } 1828 catch( const uno::Exception& ) 1829 { 1830 DBG_UNHANDLED_EXCEPTION("basic"); 1831 return; 1832 } 1833 1834 // open the source storage which might be used to copy yet-unmodified libraries 1835 try 1836 { 1837 if ( mxStorage->hasByName( maLibrariesDir ) || bInplaceStorage ) 1838 { 1839 xSourceLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, 1840 bInplaceStorage ? embed::ElementModes::READWRITE : embed::ElementModes::READ ); 1841 } 1842 } 1843 catch( const uno::Exception& ) 1844 { 1845 DBG_UNHANDLED_EXCEPTION("basic"); 1846 return; 1847 } 1848 } 1849 1850 int iArray = 0; 1851 pName = aNames.getConstArray(); 1852 ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs; 1853 std::unique_ptr< ::xmlscript::LibDescriptorArray > pLibArray(new ::xmlscript::LibDescriptorArray(nLibsToSave)); 1854 for( ; pName != pNamesEnd; ++pName ) 1855 { 1856 SfxLibrary* pImplLib = getImplLib( *pName ); 1857 if( pImplLib->mbSharedIndexFile ) 1858 { 1859 continue; 1860 } 1861 const bool bExtensionLib = pImplLib->mbExtension; 1862 ::xmlscript::LibDescriptor& rLib = bExtensionLib ? 1863 aLibDescriptorForExtensionLibs : pLibArray->mpLibs[iArray]; 1864 if( !bExtensionLib ) 1865 { 1866 iArray++; 1867 } 1868 rLib.aName = *pName; 1869 1870 rLib.bLink = pImplLib->mbLink; 1871 if( !bStorage || pImplLib->mbLink ) 1872 { 1873 rLib.aStorageURL = ( pImplLib->maUnexpandedStorageURL.getLength() ) ? 1874 pImplLib->maUnexpandedStorageURL : pImplLib->maLibInfoFileURL; 1875 } 1876 rLib.bReadOnly = pImplLib->mbReadOnly; 1877 rLib.bPreload = pImplLib->mbPreload; 1878 rLib.bPasswordProtected = pImplLib->mbPasswordProtected; 1879 rLib.aElementNames = pImplLib->getElementNames(); 1880 1881 if( pImplLib->implIsModified() || bComplete ) 1882 { 1883 // Testing pImplLib->implIsModified() is not reliable, 1884 // IMHO the value of pImplLib->implIsModified() should 1885 // reflect whether the library ( in-memory ) model 1886 // is in sync with the library container's own storage. Currently 1887 // whenever the library model is written to *any* storage 1888 // pImplLib->implSetModified( sal_False ) is called 1889 // The way the code works, especially the way that sfx uses 1890 // temp storage when saving ( and later sets the root storage of the 1891 // library container ) and similar madness in dbaccess means some surgery 1892 // is required to make it possible to successfully use this optimisation 1893 // It would be possible to do the implSetModified() call below only 1894 // conditionally, but that would require an additional boolean to be 1895 // passed in via the XStorageBasedDocument::storeLibrariesToStorage()... 1896 // fdo#68983: If there's a password and the password is not known, only 1897 // copying the storage works! 1898 // Can we simply copy the storage? 1899 bool isCopyStorage = !mbOldInfoFormat && !mbOasis2OOoFormat 1900 && !pImplLib->isLoadedStorable() 1901 && xSourceLibrariesStor.is() /* null for user profile */; 1902 if (isCopyStorage) 1903 { 1904 try 1905 { 1906 (void)xSourceLibrariesStor->isStorageElement(rLib.aName); 1907 } 1908 catch (container::NoSuchElementException const&) 1909 { 1910 isCopyStorage = false; 1911 } 1912 } 1913 if (isCopyStorage) 1914 { 1915 try 1916 { 1917 xSourceLibrariesStor->copyElementTo( rLib.aName, xTargetLibrariesStor, rLib.aName ); 1918 } 1919 catch( const uno::Exception& ) 1920 { 1921 DBG_UNHANDLED_EXCEPTION("basic"); 1922 // TODO: error handling? 1923 } 1924 } 1925 else 1926 { 1927 uno::Reference< embed::XStorage > xLibraryStor; 1928 if( bStorage ) 1929 { 1930 #if OSL_DEBUG_LEVEL > 0 1931 try 1932 { 1933 #endif 1934 xLibraryStor = xTargetLibrariesStor->openStorageElement( 1935 rLib.aName, 1936 embed::ElementModes::READWRITE ); 1937 #if OSL_DEBUG_LEVEL > 0 1938 } 1939 catch(const uno::Exception& ) 1940 { 1941 Any aError( ::cppu::getCaughtException() ); 1942 SAL_WARN( 1943 "basic", 1944 "couldn't create sub storage for library \"" 1945 << rLib.aName << "\". Exception: " 1946 << comphelper::anyToString(aError)); 1947 throw; 1948 } 1949 #endif 1950 } 1951 1952 // Maybe lib is not loaded?! 1953 if( bComplete ) 1954 { 1955 loadLibrary( rLib.aName ); 1956 } 1957 if( pImplLib->mbPasswordProtected ) 1958 { 1959 implStorePasswordLibrary( pImplLib, rLib.aName, xLibraryStor, uno::Reference< task::XInteractionHandler >() ); 1960 // TODO: Check return value 1961 } 1962 else 1963 { 1964 implStoreLibrary( pImplLib, rLib.aName, xLibraryStor ); 1965 } 1966 implStoreLibraryIndexFile( pImplLib, rLib, xLibraryStor ); 1967 if( bStorage ) 1968 { 1969 try 1970 { 1971 uno::Reference< embed::XTransactedObject > xTransact( xLibraryStor, uno::UNO_QUERY_THROW ); 1972 xTransact->commit(); 1973 } 1974 catch(const uno::Exception& ) 1975 { 1976 DBG_UNHANDLED_EXCEPTION("basic"); 1977 // TODO: error handling 1978 throw; 1979 } 1980 } 1981 } 1982 maModifiable.setModified( true ); 1983 pImplLib->implSetModified( false ); 1984 } 1985 1986 // For container info ReadOnly refers to mbReadOnlyLink 1987 rLib.bReadOnly = pImplLib->mbReadOnlyLink; 1988 } 1989 1990 // if we did an in-place save into a storage (i.e. a save into the storage we were already based on), 1991 // then we need to clean up the temporary storage we used for this 1992 if ( bInplaceStorage && !sTempTargetStorName.isEmpty() ) 1993 { 1994 SAL_WARN_IF( 1995 !xSourceLibrariesStor.is(), "basic", 1996 ("SfxLibrariesContainer::storeLibraries_impl: unexpected: we should" 1997 " have a source storage here!")); 1998 try 1999 { 2000 // for this, we first remove everything from the source storage, then copy the complete content 2001 // from the temporary target storage. From then on, what used to be the "source storage" becomes 2002 // the "target storage" for all subsequent operations. 2003 2004 // (We cannot simply remove the storage, denoted by maLibrariesDir, from i_rStorage - there might be 2005 // open references to it.) 2006 2007 if ( xSourceLibrariesStor.is() ) 2008 { 2009 // remove 2010 const Sequence< OUString > aRemoveNames( xSourceLibrariesStor->getElementNames() ); 2011 for ( auto const & removeName : aRemoveNames ) 2012 { 2013 xSourceLibrariesStor->removeElement( removeName ); 2014 } 2015 2016 // copy 2017 const Sequence< OUString > aCopyNames( xTargetLibrariesStor->getElementNames() ); 2018 for ( auto const & copyName : aCopyNames ) 2019 { 2020 xTargetLibrariesStor->copyElementTo( copyName, xSourceLibrariesStor, copyName ); 2021 } 2022 } 2023 2024 // close and remove temp target 2025 xTargetLibrariesStor->dispose(); 2026 i_rStorage->removeElement( sTempTargetStorName ); 2027 xTargetLibrariesStor.clear(); 2028 sTempTargetStorName.clear(); 2029 2030 // adjust target 2031 xTargetLibrariesStor = xSourceLibrariesStor; 2032 xSourceLibrariesStor.clear(); 2033 } 2034 catch( const Exception& ) 2035 { 2036 DBG_UNHANDLED_EXCEPTION("basic"); 2037 throw; 2038 } 2039 } 2040 2041 if( !mbOldInfoFormat && !maModifiable.isModified() ) 2042 { 2043 return; 2044 } 2045 maModifiable.setModified( false ); 2046 mbOldInfoFormat = false; 2047 2048 // Write library container info 2049 // Create sax writer 2050 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext); 2051 2052 // Write info file 2053 uno::Reference< io::XOutputStream > xOut; 2054 uno::Reference< io::XStream > xInfoStream; 2055 if( bStorage ) 2056 { 2057 OUString aStreamName = maInfoFileName + "-lc.xml"; 2058 2059 try 2060 { 2061 xInfoStream = xTargetLibrariesStor->openStreamElement( aStreamName, embed::ElementModes::READWRITE ); 2062 uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY_THROW ); 2063 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) ); 2064 2065 // #87671 Allow encryption 2066 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) ); 2067 2068 xOut = xInfoStream->getOutputStream(); 2069 } 2070 catch(const uno::Exception& ) 2071 { 2072 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 2073 } 2074 } 2075 else 2076 { 2077 // Create Output stream 2078 INetURLObject aLibInfoInetObj( maLibraryPath.getToken(1, ';') ); 2079 aLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 2080 aLibInfoInetObj.setExtension( "xlc" ); 2081 OUString aLibInfoPath( aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); 2082 2083 try 2084 { 2085 if( mxSFI->exists( aLibInfoPath ) ) 2086 { 2087 mxSFI->kill( aLibInfoPath ); 2088 } 2089 xOut = mxSFI->openFileWrite( aLibInfoPath ); 2090 } 2091 catch(const Exception& ) 2092 { 2093 xOut.clear(); 2094 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath ); 2095 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 2096 } 2097 2098 } 2099 if( !xOut.is() ) 2100 { 2101 SAL_WARN("basic", "couldn't open output stream"); 2102 return; 2103 } 2104 2105 xWriter->setOutputStream( xOut ); 2106 2107 try 2108 { 2109 xmlscript::exportLibraryContainer( xWriter, pLibArray.get() ); 2110 if ( bStorage ) 2111 { 2112 uno::Reference< embed::XTransactedObject > xTransact( xTargetLibrariesStor, uno::UNO_QUERY_THROW ); 2113 xTransact->commit(); 2114 } 2115 } 2116 catch(const uno::Exception& ) 2117 { 2118 SAL_WARN("basic", "Problem during storing of libraries!"); 2119 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 2120 } 2121 } 2122 2123 2124 // Methods XElementAccess 2125 Type SAL_CALL SfxLibraryContainer::getElementType() 2126 { 2127 LibraryContainerMethodGuard aGuard( *this ); 2128 return maNameContainer->getElementType(); 2129 } 2130 2131 sal_Bool SfxLibraryContainer::hasElements() 2132 { 2133 LibraryContainerMethodGuard aGuard( *this ); 2134 bool bRet = maNameContainer->hasElements(); 2135 return bRet; 2136 } 2137 2138 // Methods XNameAccess 2139 Any SfxLibraryContainer::getByName( const OUString& aName ) 2140 { 2141 LibraryContainerMethodGuard aGuard( *this ); 2142 Any aRetAny = maNameContainer->getByName( aName ) ; 2143 return aRetAny; 2144 } 2145 2146 Sequence< OUString > SfxLibraryContainer::getElementNames() 2147 { 2148 LibraryContainerMethodGuard aGuard( *this ); 2149 return maNameContainer->getElementNames(); 2150 } 2151 2152 sal_Bool SfxLibraryContainer::hasByName( const OUString& aName ) 2153 { 2154 LibraryContainerMethodGuard aGuard( *this ); 2155 return maNameContainer->hasByName( aName ) ; 2156 } 2157 2158 // Methods XLibraryContainer 2159 Reference< XNameContainer > SAL_CALL SfxLibraryContainer::createLibrary( const OUString& Name ) 2160 { 2161 LibraryContainerMethodGuard aGuard( *this ); 2162 SfxLibrary* pNewLib = implCreateLibrary( Name ); 2163 pNewLib->maLibElementFileExtension = maLibElementFileExtension; 2164 2165 createVariableURL( pNewLib->maUnexpandedStorageURL, Name, maInfoFileName, true ); 2166 2167 Reference< XNameAccess > xNameAccess = static_cast< XNameAccess* >( pNewLib ); 2168 Any aElement; 2169 aElement <<= xNameAccess; 2170 maNameContainer->insertByName( Name, aElement ); 2171 maModifiable.setModified( true ); 2172 Reference< XNameContainer > xRet( xNameAccess, UNO_QUERY ); 2173 return xRet; 2174 } 2175 2176 Reference< XNameAccess > SAL_CALL SfxLibraryContainer::createLibraryLink 2177 ( const OUString& Name, const OUString& StorageURL, sal_Bool ReadOnly ) 2178 { 2179 LibraryContainerMethodGuard aGuard( *this ); 2180 // TODO: Check other reasons to force ReadOnly status 2181 //if( !ReadOnly ) 2182 //{ 2183 //} 2184 2185 OUString aLibInfoFileURL; 2186 OUString aLibDirURL; 2187 OUString aUnexpandedStorageURL; 2188 checkStorageURL( StorageURL, aLibInfoFileURL, aLibDirURL, aUnexpandedStorageURL ); 2189 2190 2191 SfxLibrary* pNewLib = implCreateLibraryLink( Name, aLibInfoFileURL, aLibDirURL, ReadOnly ); 2192 pNewLib->maLibElementFileExtension = maLibElementFileExtension; 2193 pNewLib->maUnexpandedStorageURL = aUnexpandedStorageURL; 2194 pNewLib->maOriginalStorageURL = StorageURL; 2195 2196 uno::Reference< embed::XStorage > xDummyStor; 2197 ::xmlscript::LibDescriptor aLibDesc; 2198 implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, OUString() ); 2199 implImportLibDescriptor( pNewLib, aLibDesc ); 2200 2201 Reference< XNameAccess > xRet = static_cast< XNameAccess* >( pNewLib ); 2202 Any aElement; 2203 aElement <<= xRet; 2204 maNameContainer->insertByName( Name, aElement ); 2205 maModifiable.setModified( true ); 2206 2207 if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 ) 2208 { 2209 pNewLib->mbExtension = true; 2210 } 2211 else if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1 2212 || StorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 ) 2213 { 2214 pNewLib->mbExtension = true; 2215 pNewLib->mbReadOnly = true; 2216 } 2217 2218 return xRet; 2219 } 2220 2221 void SAL_CALL SfxLibraryContainer::removeLibrary( const OUString& Name ) 2222 { 2223 LibraryContainerMethodGuard aGuard( *this ); 2224 // Get and hold library before removing 2225 Any aLibAny = maNameContainer->getByName( Name ) ; 2226 Reference< XNameAccess > xNameAccess; 2227 aLibAny >>= xNameAccess; 2228 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); 2229 if( pImplLib->mbReadOnly && !pImplLib->mbLink ) 2230 { 2231 throw IllegalArgumentException(); 2232 } 2233 // Remove from container 2234 maNameContainer->removeByName( Name ); 2235 maModifiable.setModified( true ); 2236 2237 // Delete library files, but not for linked libraries 2238 if( !pImplLib->mbLink ) 2239 { 2240 if( mxStorage.is() ) 2241 { 2242 return; 2243 } 2244 if( xNameAccess->hasElements() ) 2245 { 2246 Sequence< OUString > aNames = pImplLib->getElementNames(); 2247 sal_Int32 nNameCount = aNames.getLength(); 2248 const OUString* pNames = aNames.getConstArray(); 2249 for( sal_Int32 i = 0 ; i < nNameCount ; ++i, ++pNames ) 2250 { 2251 pImplLib->removeElementWithoutChecks( *pNames, SfxLibrary::LibraryContainerAccess() ); 2252 } 2253 } 2254 2255 // Delete index file 2256 createAppLibraryFolder( pImplLib, Name ); 2257 OUString aLibInfoPath = pImplLib->maLibInfoFileURL; 2258 try 2259 { 2260 if( mxSFI->exists( aLibInfoPath ) ) 2261 { 2262 mxSFI->kill( aLibInfoPath ); 2263 } 2264 } 2265 catch(const Exception& ) {} 2266 2267 // Delete folder if empty 2268 INetURLObject aInetObj( maLibraryPath.getToken(1, ';') ); 2269 aInetObj.insertName( Name, true, INetURLObject::LAST_SEGMENT, 2270 INetURLObject::EncodeMechanism::All ); 2271 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 2272 2273 try 2274 { 2275 if( mxSFI->isFolder( aLibDirPath ) ) 2276 { 2277 Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true ); 2278 sal_Int32 nCount = aContentSeq.getLength(); 2279 if( !nCount ) 2280 { 2281 mxSFI->kill( aLibDirPath ); 2282 } 2283 } 2284 } 2285 catch(const Exception& ) 2286 { 2287 } 2288 } 2289 } 2290 2291 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLoaded( const OUString& Name ) 2292 { 2293 LibraryContainerMethodGuard aGuard( *this ); 2294 SfxLibrary* pImplLib = getImplLib( Name ); 2295 bool bRet = pImplLib->mbLoaded; 2296 return bRet; 2297 } 2298 2299 2300 void SAL_CALL SfxLibraryContainer::loadLibrary( const OUString& Name ) 2301 { 2302 LibraryContainerMethodGuard aGuard( *this ); 2303 Any aLibAny = maNameContainer->getByName( Name ) ; 2304 Reference< XNameAccess > xNameAccess; 2305 aLibAny >>= xNameAccess; 2306 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); 2307 2308 bool bLoaded = pImplLib->mbLoaded; 2309 pImplLib->mbLoaded = true; 2310 if( !bLoaded && xNameAccess->hasElements() ) 2311 { 2312 if( pImplLib->mbPasswordProtected ) 2313 { 2314 implLoadPasswordLibrary( pImplLib, Name ); 2315 return; 2316 } 2317 2318 bool bLink = pImplLib->mbLink; 2319 bool bStorage = mxStorage.is() && !bLink; 2320 2321 uno::Reference< embed::XStorage > xLibrariesStor; 2322 uno::Reference< embed::XStorage > xLibraryStor; 2323 if( bStorage ) 2324 { 2325 #if OSL_DEBUG_LEVEL > 0 2326 try 2327 { 2328 #endif 2329 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); 2330 SAL_WARN_IF( 2331 !xLibrariesStor.is(), "basic", 2332 ("The method must either throw exception or return a" 2333 " storage!")); 2334 if ( !xLibrariesStor.is() ) 2335 { 2336 throw uno::RuntimeException("null returned from openStorageElement"); 2337 } 2338 2339 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ ); 2340 SAL_WARN_IF( 2341 !xLibraryStor.is(), "basic", 2342 ("The method must either throw exception or return a" 2343 " storage!")); 2344 if ( !xLibrariesStor.is() ) 2345 { 2346 throw uno::RuntimeException("null returned from openStorageElement"); 2347 } 2348 #if OSL_DEBUG_LEVEL > 0 2349 } 2350 catch(const uno::Exception& ) 2351 { 2352 Any aError( ::cppu::getCaughtException() ); 2353 SAL_WARN( 2354 "basic", 2355 "couldn't open sub storage for library \"" << Name 2356 << "\". Exception: " 2357 << comphelper::anyToString(aError)); 2358 throw; 2359 } 2360 #endif 2361 } 2362 2363 Sequence< OUString > aNames = pImplLib->getElementNames(); 2364 sal_Int32 nNameCount = aNames.getLength(); 2365 const OUString* pNames = aNames.getConstArray(); 2366 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 2367 { 2368 OUString aElementName = pNames[ i ]; 2369 2370 OUString aFile; 2371 uno::Reference< io::XInputStream > xInStream; 2372 2373 if( bStorage ) 2374 { 2375 uno::Reference< io::XStream > xElementStream; 2376 2377 aFile = aElementName + ".xml"; 2378 2379 try 2380 { 2381 xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ ); 2382 } 2383 catch(const uno::Exception& ) 2384 {} 2385 2386 if( !xElementStream.is() ) 2387 { 2388 // Check for EA2 document version with wrong extensions 2389 aFile = aElementName + "." + maLibElementFileExtension; 2390 try 2391 { 2392 xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ ); 2393 } 2394 catch(const uno::Exception& ) 2395 {} 2396 } 2397 2398 if ( xElementStream.is() ) 2399 { 2400 xInStream = xElementStream->getInputStream(); 2401 } 2402 if ( !xInStream.is() ) 2403 { 2404 SAL_WARN( 2405 "basic", 2406 "couldn't open library element stream - attempted to" 2407 " open library \"" << Name << '"'); 2408 throw RuntimeException("couldn't open library element stream", *this); 2409 } 2410 } 2411 else 2412 { 2413 OUString aLibDirPath = pImplLib->maStorageURL; 2414 INetURLObject aElementInetObj( aLibDirPath ); 2415 aElementInetObj.insertName( aElementName, false, 2416 INetURLObject::LAST_SEGMENT, 2417 INetURLObject::EncodeMechanism::All ); 2418 aElementInetObj.setExtension( maLibElementFileExtension ); 2419 aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 2420 } 2421 2422 Reference< XNameContainer > xLib( pImplLib ); 2423 Any aAny = importLibraryElement( xLib, aElementName, 2424 aFile, xInStream ); 2425 if( pImplLib->hasByName( aElementName ) ) 2426 { 2427 if( aAny.hasValue() ) 2428 { 2429 pImplLib->maNameContainer->replaceByName( aElementName, aAny ); 2430 } 2431 } 2432 else 2433 { 2434 pImplLib->maNameContainer->insertNoCheck(aElementName, aAny); 2435 } 2436 } 2437 pImplLib->implSetModified( false ); 2438 } 2439 } 2440 2441 // Methods XLibraryContainer2 2442 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLink( const OUString& Name ) 2443 { 2444 LibraryContainerMethodGuard aGuard( *this ); 2445 SfxLibrary* pImplLib = getImplLib( Name ); 2446 bool bRet = pImplLib->mbLink; 2447 return bRet; 2448 } 2449 2450 OUString SAL_CALL SfxLibraryContainer::getLibraryLinkURL( const OUString& Name ) 2451 { 2452 LibraryContainerMethodGuard aGuard( *this ); 2453 SfxLibrary* pImplLib = getImplLib( Name ); 2454 bool bLink = pImplLib->mbLink; 2455 if( !bLink ) 2456 { 2457 throw IllegalArgumentException(); 2458 } 2459 OUString aRetStr = pImplLib->maLibInfoFileURL; 2460 return aRetStr; 2461 } 2462 2463 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryReadOnly( const OUString& Name ) 2464 { 2465 LibraryContainerMethodGuard aGuard( *this ); 2466 SfxLibrary* pImplLib = getImplLib( Name ); 2467 bool bRet = pImplLib->mbReadOnly || (pImplLib->mbLink && pImplLib->mbReadOnlyLink); 2468 return bRet; 2469 } 2470 2471 void SAL_CALL SfxLibraryContainer::setLibraryReadOnly( const OUString& Name, sal_Bool bReadOnly ) 2472 { 2473 LibraryContainerMethodGuard aGuard( *this ); 2474 SfxLibrary* pImplLib = getImplLib( Name ); 2475 if( pImplLib->mbLink ) 2476 { 2477 if( pImplLib->mbReadOnlyLink != bool(bReadOnly) ) 2478 { 2479 pImplLib->mbReadOnlyLink = bReadOnly; 2480 pImplLib->implSetModified( true ); 2481 maModifiable.setModified( true ); 2482 } 2483 } 2484 else 2485 { 2486 if( pImplLib->mbReadOnly != bool(bReadOnly) ) 2487 { 2488 pImplLib->mbReadOnly = bReadOnly; 2489 pImplLib->implSetModified( true ); 2490 } 2491 } 2492 } 2493 2494 void SAL_CALL SfxLibraryContainer::renameLibrary( const OUString& Name, const OUString& NewName ) 2495 { 2496 LibraryContainerMethodGuard aGuard( *this ); 2497 if( maNameContainer->hasByName( NewName ) ) 2498 { 2499 throw ElementExistException(); 2500 } 2501 // Get and hold library before removing 2502 Any aLibAny = maNameContainer->getByName( Name ) ; 2503 2504 // #i24094 Maybe lib is not loaded! 2505 Reference< XNameAccess > xNameAccess; 2506 aLibAny >>= xNameAccess; 2507 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); 2508 if( pImplLib->mbPasswordProtected && !pImplLib->mbPasswordVerified ) 2509 { 2510 return; // Lib with unverified password cannot be renamed 2511 } 2512 loadLibrary( Name ); 2513 2514 // Remove from container 2515 maNameContainer->removeByName( Name ); 2516 maModifiable.setModified( true ); 2517 2518 // Rename library folder, but not for linked libraries 2519 bool bMovedSuccessful = true; 2520 2521 // Rename files 2522 bool bStorage = mxStorage.is(); 2523 if( !bStorage && !pImplLib->mbLink ) 2524 { 2525 bMovedSuccessful = false; 2526 2527 OUString aLibDirPath = pImplLib->maStorageURL; 2528 2529 INetURLObject aDestInetObj( maLibraryPath.getToken(1, ';')); 2530 aDestInetObj.insertName( NewName, true, INetURLObject::LAST_SEGMENT, 2531 INetURLObject::EncodeMechanism::All ); 2532 OUString aDestDirPath = aDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 2533 2534 // Store new URL 2535 OUString aLibInfoFileURL = pImplLib->maLibInfoFileURL; 2536 checkStorageURL( aDestDirPath, pImplLib->maLibInfoFileURL, pImplLib->maStorageURL, 2537 pImplLib->maUnexpandedStorageURL ); 2538 2539 try 2540 { 2541 if( mxSFI->isFolder( aLibDirPath ) ) 2542 { 2543 if( !mxSFI->isFolder( aDestDirPath ) ) 2544 { 2545 mxSFI->createFolder( aDestDirPath ); 2546 } 2547 // Move index file 2548 try 2549 { 2550 if( mxSFI->exists( pImplLib->maLibInfoFileURL ) ) 2551 { 2552 mxSFI->kill( pImplLib->maLibInfoFileURL ); 2553 } 2554 mxSFI->move( aLibInfoFileURL, pImplLib->maLibInfoFileURL ); 2555 } 2556 catch(const Exception& ) 2557 { 2558 } 2559 2560 Sequence< OUString > aElementNames = xNameAccess->getElementNames(); 2561 sal_Int32 nNameCount = aElementNames.getLength(); 2562 const OUString* pNames = aElementNames.getConstArray(); 2563 for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) 2564 { 2565 OUString aElementName = pNames[ i ]; 2566 2567 INetURLObject aElementInetObj( aLibDirPath ); 2568 aElementInetObj.insertName( aElementName, false, 2569 INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); 2570 aElementInetObj.setExtension( maLibElementFileExtension ); 2571 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); 2572 2573 INetURLObject aElementDestInetObj( aDestDirPath ); 2574 aElementDestInetObj.insertName( aElementName, false, 2575 INetURLObject::LAST_SEGMENT, 2576 INetURLObject::EncodeMechanism::All ); 2577 aElementDestInetObj.setExtension( maLibElementFileExtension ); 2578 OUString aDestElementPath( aElementDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); 2579 2580 try 2581 { 2582 if( mxSFI->exists( aDestElementPath ) ) 2583 { 2584 mxSFI->kill( aDestElementPath ); 2585 } 2586 mxSFI->move( aElementPath, aDestElementPath ); 2587 } 2588 catch(const Exception& ) 2589 { 2590 } 2591 } 2592 pImplLib->storeResourcesAsURL( aDestDirPath, NewName ); 2593 2594 // Delete folder if empty 2595 Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true ); 2596 sal_Int32 nCount = aContentSeq.getLength(); 2597 if( !nCount ) 2598 { 2599 mxSFI->kill( aLibDirPath ); 2600 } 2601 2602 bMovedSuccessful = true; 2603 pImplLib->implSetModified( true ); 2604 } 2605 } 2606 catch(const Exception& ) 2607 { 2608 // Restore old library 2609 maNameContainer->insertByName( Name, aLibAny ) ; 2610 } 2611 } 2612 2613 if( bStorage && !pImplLib->mbLink ) 2614 { 2615 pImplLib->implSetModified( true ); 2616 } 2617 if( bMovedSuccessful ) 2618 { 2619 maNameContainer->insertByName( NewName, aLibAny ) ; 2620 } 2621 } 2622 2623 2624 // Methods XInitialization 2625 void SAL_CALL SfxLibraryContainer::initialize( const Sequence< Any >& _rArguments ) 2626 { 2627 LibraryContainerMethodGuard aGuard( *this ); 2628 sal_Int32 nArgCount = _rArguments.getLength(); 2629 if ( nArgCount == 1 ) 2630 { 2631 OUString sInitialDocumentURL; 2632 Reference< XStorageBasedDocument > xDocument; 2633 if ( _rArguments[0] >>= sInitialDocumentURL ) 2634 { 2635 init( sInitialDocumentURL, nullptr ); 2636 return; 2637 } 2638 2639 if ( _rArguments[0] >>= xDocument ) 2640 { 2641 initializeFromDocument( xDocument ); 2642 return; 2643 } 2644 } 2645 2646 throw IllegalArgumentException(); 2647 } 2648 2649 void SfxLibraryContainer::initializeFromDocument( const Reference< XStorageBasedDocument >& _rxDocument ) 2650 { 2651 // check whether this is a valid OfficeDocument, and obtain the document's root storage 2652 Reference< XStorage > xDocStorage; 2653 try 2654 { 2655 Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY_THROW ); 2656 if ( xSI->supportsService("com.sun.star.document.OfficeDocument")) 2657 { 2658 xDocStorage.set( _rxDocument->getDocumentStorage(), UNO_QUERY_THROW ); 2659 } 2660 Reference< XModel > xDocument( _rxDocument, UNO_QUERY_THROW ); 2661 Reference< XComponent > xDocComponent( _rxDocument, UNO_QUERY_THROW ); 2662 2663 mxOwnerDocument = xDocument; 2664 startComponentListening( xDocComponent ); 2665 } 2666 catch( const Exception& ) { } 2667 2668 if ( !xDocStorage.is() ) 2669 { 2670 throw IllegalArgumentException(); 2671 } 2672 init( OUString(), xDocStorage ); 2673 } 2674 2675 // OEventListenerAdapter 2676 void SfxLibraryContainer::_disposing( const EventObject& _rSource ) 2677 { 2678 #if OSL_DEBUG_LEVEL > 0 2679 Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY ); 2680 SAL_WARN_IF( 2681 xDocument != _rSource.Source || !xDocument.is(), "basic", 2682 "SfxLibraryContainer::_disposing: where does this come from?"); 2683 #else 2684 (void)_rSource; 2685 #endif 2686 dispose(); 2687 } 2688 2689 // OComponentHelper 2690 void SAL_CALL SfxLibraryContainer::disposing() 2691 { 2692 Reference< XModel > xModel = mxOwnerDocument; 2693 EventObject aEvent( xModel.get() ); 2694 maVBAScriptListeners.disposing( aEvent ); 2695 stopAllComponentListening(); 2696 mxOwnerDocument.clear(); 2697 } 2698 2699 // Methods XLibraryContainerPassword 2700 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordProtected( const OUString& ) 2701 { 2702 return false; 2703 } 2704 2705 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordVerified( const OUString& ) 2706 { 2707 throw IllegalArgumentException(); 2708 } 2709 2710 sal_Bool SAL_CALL SfxLibraryContainer::verifyLibraryPassword( const OUString&, const OUString& ) 2711 { 2712 throw IllegalArgumentException(); 2713 } 2714 2715 void SAL_CALL SfxLibraryContainer::changeLibraryPassword(const OUString&, const OUString&, const OUString& ) 2716 { 2717 throw IllegalArgumentException(); 2718 } 2719 2720 // Methods XContainer 2721 void SAL_CALL SfxLibraryContainer::addContainerListener( const Reference< XContainerListener >& xListener ) 2722 { 2723 LibraryContainerMethodGuard aGuard( *this ); 2724 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) ); 2725 maNameContainer->addContainerListener( xListener ); 2726 } 2727 2728 void SAL_CALL SfxLibraryContainer::removeContainerListener( const Reference< XContainerListener >& xListener ) 2729 { 2730 LibraryContainerMethodGuard aGuard( *this ); 2731 maNameContainer->removeContainerListener( xListener ); 2732 } 2733 2734 // Methods XLibraryContainerExport 2735 void SAL_CALL SfxLibraryContainer::exportLibrary( const OUString& Name, const OUString& URL, 2736 const Reference< XInteractionHandler >& Handler ) 2737 { 2738 LibraryContainerMethodGuard aGuard( *this ); 2739 SfxLibrary* pImplLib = getImplLib( Name ); 2740 2741 Reference< XSimpleFileAccess3 > xToUseSFI; 2742 if( Handler.is() ) 2743 { 2744 xToUseSFI = ucb::SimpleFileAccess::create( mxContext ); 2745 xToUseSFI->setInteractionHandler( Handler ); 2746 } 2747 2748 // Maybe lib is not loaded?! 2749 loadLibrary( Name ); 2750 2751 uno::Reference< css::embed::XStorage > xDummyStor; 2752 if( pImplLib->mbPasswordProtected ) 2753 { 2754 implStorePasswordLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler ); 2755 } 2756 else 2757 { 2758 implStoreLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler ); 2759 } 2760 ::xmlscript::LibDescriptor aLibDesc; 2761 aLibDesc.aName = Name; 2762 aLibDesc.bLink = false; // Link status gets lost? 2763 aLibDesc.bReadOnly = pImplLib->mbReadOnly; 2764 aLibDesc.bPreload = false; // Preload status gets lost? 2765 aLibDesc.bPasswordProtected = pImplLib->mbPasswordProtected; 2766 aLibDesc.aElementNames = pImplLib->getElementNames(); 2767 2768 implStoreLibraryIndexFile( pImplLib, aLibDesc, xDummyStor, URL, xToUseSFI ); 2769 } 2770 2771 OUString SfxLibraryContainer::expand_url( const OUString& url ) 2772 { 2773 if (url.startsWithIgnoreAsciiCase( "vnd.sun.star.expand:" )) 2774 { 2775 return comphelper::getExpandedUri(mxContext, url); 2776 } 2777 else if( mxStringSubstitution.is() ) 2778 { 2779 OUString ret( mxStringSubstitution->substituteVariables( url, false ) ); 2780 return ret; 2781 } 2782 else 2783 { 2784 return url; 2785 } 2786 } 2787 2788 //XLibraryContainer3 2789 OUString SAL_CALL SfxLibraryContainer::getOriginalLibraryLinkURL( const OUString& Name ) 2790 { 2791 LibraryContainerMethodGuard aGuard( *this ); 2792 SfxLibrary* pImplLib = getImplLib( Name ); 2793 bool bLink = pImplLib->mbLink; 2794 if( !bLink ) 2795 { 2796 throw IllegalArgumentException(); 2797 } 2798 OUString aRetStr = pImplLib->maOriginalStorageURL; 2799 return aRetStr; 2800 } 2801 2802 2803 // XVBACompatibility 2804 sal_Bool SAL_CALL SfxLibraryContainer::getVBACompatibilityMode() 2805 { 2806 return mbVBACompat; 2807 } 2808 2809 void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( sal_Bool _vbacompatmodeon ) 2810 { 2811 /* The member variable mbVBACompat must be set first, the following call 2812 to getBasicManager() may call getVBACompatibilityMode() which returns 2813 this value. */ 2814 mbVBACompat = _vbacompatmodeon; 2815 if( BasicManager* pBasMgr = getBasicManager() ) 2816 { 2817 // get the standard library 2818 OUString aLibName = pBasMgr->GetName(); 2819 if ( aLibName.isEmpty()) 2820 { 2821 aLibName = "Standard"; 2822 } 2823 if( StarBASIC* pBasic = pBasMgr->GetLib( aLibName ) ) 2824 { 2825 pBasic->SetVBAEnabled( _vbacompatmodeon ); 2826 } 2827 /* If in VBA compatibility mode, force creation of the VBA Globals 2828 object. Each application will create an instance of its own 2829 implementation and store it in its Basic manager. Implementations 2830 will do all necessary additional initialization, such as 2831 registering the global "This***Doc" UNO constant, starting the 2832 document events processor etc. 2833 */ 2834 if( mbVBACompat ) try 2835 { 2836 Reference< XModel > xModel( mxOwnerDocument ); // weak-ref -> ref 2837 Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); 2838 xFactory->createInstance("ooo.vba.VBAGlobals"); 2839 } 2840 catch(const Exception& ) 2841 { 2842 } 2843 } 2844 } 2845 2846 void SAL_CALL SfxLibraryContainer::setProjectName( const OUString& _projectname ) 2847 { 2848 msProjectName = _projectname; 2849 BasicManager* pBasMgr = getBasicManager(); 2850 // Temporary HACK 2851 // Some parts of the VBA handling ( e.g. in core basic ) 2852 // code expect the name of the VBA project to be set as the name of 2853 // the basic manager. Provide fail back here. 2854 if( pBasMgr ) 2855 { 2856 pBasMgr->SetName( msProjectName ); 2857 } 2858 } 2859 2860 sal_Int32 SAL_CALL SfxLibraryContainer::getRunningVBAScripts() 2861 { 2862 LibraryContainerMethodGuard aGuard( *this ); 2863 return mnRunningVBAScripts; 2864 } 2865 2866 void SAL_CALL SfxLibraryContainer::addVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener ) 2867 { 2868 maVBAScriptListeners.addTypedListener( rxListener ); 2869 } 2870 2871 void SAL_CALL SfxLibraryContainer::removeVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener ) 2872 { 2873 maVBAScriptListeners.removeTypedListener( rxListener ); 2874 } 2875 2876 void SAL_CALL SfxLibraryContainer::broadcastVBAScriptEvent( sal_Int32 nIdentifier, const OUString& rModuleName ) 2877 { 2878 // own lock for accessing the number of running scripts 2879 enterMethod(); 2880 switch( nIdentifier ) 2881 { 2882 case vba::VBAScriptEventId::SCRIPT_STARTED: 2883 ++mnRunningVBAScripts; 2884 break; 2885 case vba::VBAScriptEventId::SCRIPT_STOPPED: 2886 --mnRunningVBAScripts; 2887 break; 2888 } 2889 leaveMethod(); 2890 2891 Reference< XModel > xModel = mxOwnerDocument; // weak-ref -> ref 2892 vba::VBAScriptEvent aEvent( Reference<XInterface>(xModel, UNO_QUERY), nIdentifier, rModuleName ); 2893 maVBAScriptListeners.notify( aEvent ); 2894 } 2895 2896 // Methods XServiceInfo 2897 sal_Bool SAL_CALL SfxLibraryContainer::supportsService( const OUString& _rServiceName ) 2898 { 2899 return cppu::supportsService(this, _rServiceName); 2900 } 2901 2902 // Implementation class SfxLibrary 2903 2904 // Ctor 2905 SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType, 2906 const Reference< XSimpleFileAccess3 >& xSFI ) 2907 : OComponentHelper( m_aMutex ) 2908 , mxSFI( xSFI ) 2909 , mrModifiable( _rModifiable ) 2910 , maNameContainer( new NameContainer(aType) ) 2911 , mbLoaded( true ) 2912 , mbIsModified( true ) 2913 , mbInitialised( false ) 2914 , mbLink( false ) 2915 , mbReadOnly( false ) 2916 , mbReadOnlyLink( false ) 2917 , mbPreload( false ) 2918 , mbPasswordProtected( false ) 2919 , mbPasswordVerified( false ) 2920 , mbDoc50Password( false ) 2921 , mbSharedIndexFile( false ) 2922 , mbExtension( false ) 2923 { 2924 } 2925 2926 SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType, 2927 const Reference< XSimpleFileAccess3 >& xSFI, 2928 const OUString& aLibInfoFileURL, const OUString& aStorageURL, bool ReadOnly ) 2929 : OComponentHelper( m_aMutex ) 2930 , mxSFI( xSFI ) 2931 , mrModifiable( _rModifiable ) 2932 , maNameContainer( new NameContainer(aType) ) 2933 , mbLoaded( false ) 2934 , mbIsModified( true ) 2935 , mbInitialised( false ) 2936 , maLibInfoFileURL( aLibInfoFileURL ) 2937 , maStorageURL( aStorageURL ) 2938 , mbLink( true ) 2939 , mbReadOnly( false ) 2940 , mbReadOnlyLink( ReadOnly ) 2941 , mbPreload( false ) 2942 , mbPasswordProtected( false ) 2943 , mbPasswordVerified( false ) 2944 , mbDoc50Password( false ) 2945 , mbSharedIndexFile( false ) 2946 , mbExtension( false ) 2947 { 2948 } 2949 2950 bool SfxLibrary::isLoadedStorable() 2951 { 2952 return mbLoaded && (!mbPasswordProtected || mbPasswordVerified); 2953 } 2954 2955 void SfxLibrary::implSetModified( bool _bIsModified ) 2956 { 2957 if ( mbIsModified == _bIsModified ) 2958 { 2959 return; 2960 } 2961 mbIsModified = _bIsModified; 2962 if ( mbIsModified ) 2963 { 2964 mrModifiable.setModified( true ); 2965 } 2966 } 2967 2968 // Methods XInterface 2969 Any SAL_CALL SfxLibrary::queryInterface( const Type& rType ) 2970 { 2971 Any aRet; 2972 2973 aRet = 2974 ::cppu::queryInterface( 2975 rType, 2976 static_cast< XContainer * >( this ), 2977 static_cast< XNameContainer * >( this ), 2978 static_cast< XNameAccess * >( this ), 2979 static_cast< XElementAccess * >( this ), 2980 static_cast< XChangesNotifier * >( this ) ); 2981 if( !aRet.hasValue() ) 2982 { 2983 aRet = OComponentHelper::queryInterface( rType ); 2984 } 2985 return aRet; 2986 } 2987 2988 // Methods XElementAccess 2989 Type SfxLibrary::getElementType() 2990 { 2991 return maNameContainer->getElementType(); 2992 } 2993 2994 sal_Bool SfxLibrary::hasElements() 2995 { 2996 bool bRet = maNameContainer->hasElements(); 2997 return bRet; 2998 } 2999 3000 // Methods XNameAccess 3001 Any SfxLibrary::getByName( const OUString& aName ) 3002 { 3003 impl_checkLoaded(); 3004 3005 Any aRetAny = maNameContainer->getByName( aName ) ; 3006 return aRetAny; 3007 } 3008 3009 Sequence< OUString > SfxLibrary::getElementNames() 3010 { 3011 return maNameContainer->getElementNames(); 3012 } 3013 3014 sal_Bool SfxLibrary::hasByName( const OUString& aName ) 3015 { 3016 bool bRet = maNameContainer->hasByName( aName ); 3017 return bRet; 3018 } 3019 3020 void SfxLibrary::impl_checkReadOnly() 3021 { 3022 if( mbReadOnly || (mbLink && mbReadOnlyLink) ) 3023 { 3024 throw IllegalArgumentException( 3025 "Library is readonly.", 3026 // TODO: resource 3027 *this, 0 3028 ); 3029 } 3030 } 3031 3032 void SfxLibrary::impl_checkLoaded() 3033 { 3034 if ( !mbLoaded ) 3035 { 3036 throw WrappedTargetException( 3037 OUString(), 3038 *this, 3039 Any( LibraryNotLoadedException( 3040 OUString(), 3041 *this 3042 ) ) 3043 ); 3044 } 3045 } 3046 3047 // Methods XNameReplace 3048 void SfxLibrary::replaceByName( const OUString& aName, const Any& aElement ) 3049 { 3050 impl_checkReadOnly(); 3051 impl_checkLoaded(); 3052 3053 SAL_WARN_IF( 3054 !isLibraryElementValid(aElement), "basic", 3055 "SfxLibrary::replaceByName: replacing element is invalid!"); 3056 3057 maNameContainer->replaceByName( aName, aElement ); 3058 implSetModified( true ); 3059 } 3060 3061 3062 // Methods XNameContainer 3063 void SfxLibrary::insertByName( const OUString& aName, const Any& aElement ) 3064 { 3065 impl_checkReadOnly(); 3066 impl_checkLoaded(); 3067 3068 SAL_WARN_IF( 3069 !isLibraryElementValid(aElement), "basic", 3070 "SfxLibrary::insertByName: to-be-inserted element is invalid!"); 3071 3072 maNameContainer->insertByName( aName, aElement ); 3073 implSetModified( true ); 3074 } 3075 3076 void SfxLibrary::impl_removeWithoutChecks( const OUString& _rElementName ) 3077 { 3078 maNameContainer->removeByName( _rElementName ); 3079 implSetModified( true ); 3080 3081 // Remove element file 3082 if( !maStorageURL.isEmpty() ) 3083 { 3084 INetURLObject aElementInetObj( maStorageURL ); 3085 aElementInetObj.insertName( _rElementName, false, 3086 INetURLObject::LAST_SEGMENT, 3087 INetURLObject::EncodeMechanism::All ); 3088 aElementInetObj.setExtension( maLibElementFileExtension ); 3089 OUString aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 3090 3091 try 3092 { 3093 if( mxSFI->exists( aFile ) ) 3094 { 3095 mxSFI->kill( aFile ); 3096 } 3097 } 3098 catch(const Exception& ) 3099 { 3100 DBG_UNHANDLED_EXCEPTION("basic"); 3101 } 3102 } 3103 } 3104 3105 void SfxLibrary::removeByName( const OUString& Name ) 3106 { 3107 impl_checkReadOnly(); 3108 impl_checkLoaded(); 3109 impl_removeWithoutChecks( Name ); 3110 } 3111 3112 // XTypeProvider 3113 Sequence< Type > SfxLibrary::getTypes() 3114 { 3115 static OTypeCollection ourTypes_NameContainer( 3116 cppu::UnoType<XNameContainer>::get(), 3117 cppu::UnoType<XContainer>::get(), 3118 cppu::UnoType<XChangesNotifier>::get(), 3119 OComponentHelper::getTypes() ); 3120 3121 return ourTypes_NameContainer.getTypes(); 3122 } 3123 3124 3125 Sequence< sal_Int8 > SfxLibrary::getImplementationId() 3126 { 3127 return css::uno::Sequence<sal_Int8>(); 3128 } 3129 3130 // Methods XContainer 3131 void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener ) 3132 { 3133 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) ); 3134 maNameContainer->addContainerListener( xListener ); 3135 } 3136 3137 void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerListener >& xListener ) 3138 { 3139 maNameContainer->removeContainerListener( xListener ); 3140 } 3141 3142 // Methods XChangesNotifier 3143 void SAL_CALL SfxLibrary::addChangesListener( const Reference< XChangesListener >& xListener ) 3144 { 3145 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) ); 3146 maNameContainer->addChangesListener( xListener ); 3147 } 3148 3149 void SAL_CALL SfxLibrary::removeChangesListener( const Reference< XChangesListener >& xListener ) 3150 { 3151 maNameContainer->removeChangesListener( xListener ); 3152 } 3153 3154 3155 // Implementation class ScriptExtensionIterator 3156 3157 #define sBasicLibMediaType "application/vnd.sun.star.basic-library" 3158 #define sDialogLibMediaType "application/vnd.sun.star.dialog-library" 3159 3160 ScriptExtensionIterator::ScriptExtensionIterator() 3161 : m_xContext( comphelper::getProcessComponentContext() ) 3162 , m_eState( USER_EXTENSIONS ) 3163 , m_bUserPackagesLoaded( false ) 3164 , m_bSharedPackagesLoaded( false ) 3165 , m_bBundledPackagesLoaded( false ) 3166 , m_iUserPackage( 0 ) 3167 , m_iSharedPackage( 0 ) 3168 , m_iBundledPackage( 0 ) 3169 , m_pScriptSubPackageIterator( nullptr ) 3170 {} 3171 3172 OUString ScriptExtensionIterator::nextBasicOrDialogLibrary( bool& rbPureDialogLib ) 3173 { 3174 OUString aRetLib; 3175 3176 while( aRetLib.isEmpty() && m_eState != END_REACHED ) 3177 { 3178 switch( m_eState ) 3179 { 3180 case USER_EXTENSIONS: 3181 { 3182 Reference< deployment::XPackage > xScriptPackage = 3183 implGetNextUserScriptPackage( rbPureDialogLib ); 3184 if( !xScriptPackage.is() ) 3185 { 3186 break; 3187 } 3188 aRetLib = xScriptPackage->getURL(); 3189 break; 3190 } 3191 3192 case SHARED_EXTENSIONS: 3193 { 3194 Reference< deployment::XPackage > xScriptPackage = 3195 implGetNextSharedScriptPackage( rbPureDialogLib ); 3196 if( !xScriptPackage.is() ) 3197 { 3198 break; 3199 } 3200 aRetLib = xScriptPackage->getURL(); 3201 break; 3202 } 3203 case BUNDLED_EXTENSIONS: 3204 { 3205 Reference< deployment::XPackage > xScriptPackage = 3206 implGetNextBundledScriptPackage( rbPureDialogLib ); 3207 if( !xScriptPackage.is() ) 3208 { 3209 break; 3210 } 3211 aRetLib = xScriptPackage->getURL(); 3212 break; 3213 } 3214 case END_REACHED: 3215 SAL_WARN( 3216 "basic", 3217 ("ScriptExtensionIterator::nextBasicOrDialogLibrary():" 3218 " Invalid case END_REACHED")); 3219 break; 3220 } 3221 } 3222 3223 return aRetLib; 3224 } 3225 3226 ScriptSubPackageIterator::ScriptSubPackageIterator( Reference< deployment::XPackage > const & xMainPackage ) 3227 : m_xMainPackage( xMainPackage ) 3228 , m_bIsValid( false ) 3229 , m_bIsBundle( false ) 3230 , m_nSubPkgCount( 0 ) 3231 , m_iNextSubPkg( 0 ) 3232 { 3233 if( !m_xMainPackage.is() ) 3234 { 3235 return; 3236 } 3237 // Check if parent package is registered 3238 beans::Optional< beans::Ambiguous<sal_Bool> > option( m_xMainPackage->isRegistered 3239 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); 3240 bool bRegistered = false; 3241 if( option.IsPresent ) 3242 { 3243 beans::Ambiguous<sal_Bool> const & reg = option.Value; 3244 if( !reg.IsAmbiguous && reg.Value ) 3245 { 3246 bRegistered = true; 3247 } 3248 } 3249 if( bRegistered ) 3250 { 3251 m_bIsValid = true; 3252 if( m_xMainPackage->isBundle() ) 3253 { 3254 m_bIsBundle = true; 3255 m_aSubPkgSeq = m_xMainPackage->getBundle( Reference<task::XAbortChannel>(), 3256 Reference<ucb::XCommandEnvironment>() ); 3257 m_nSubPkgCount = m_aSubPkgSeq.getLength(); 3258 } 3259 } 3260 } 3261 3262 Reference< deployment::XPackage > ScriptSubPackageIterator::getNextScriptSubPackage( bool& rbPureDialogLib ) 3263 { 3264 rbPureDialogLib = false; 3265 3266 Reference< deployment::XPackage > xScriptPackage; 3267 if( !m_bIsValid ) 3268 { 3269 return xScriptPackage; 3270 } 3271 if( m_bIsBundle ) 3272 { 3273 const Reference< deployment::XPackage >* pSeq = m_aSubPkgSeq.getConstArray(); 3274 sal_Int32 iPkg; 3275 for( iPkg = m_iNextSubPkg ; iPkg < m_nSubPkgCount ; ++iPkg ) 3276 { 3277 const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; 3278 xScriptPackage = implDetectScriptPackage( xSubPkg, rbPureDialogLib ); 3279 if( xScriptPackage.is() ) 3280 { 3281 break; 3282 } 3283 } 3284 m_iNextSubPkg = iPkg + 1; 3285 } 3286 else 3287 { 3288 xScriptPackage = implDetectScriptPackage( m_xMainPackage, rbPureDialogLib ); 3289 m_bIsValid = false; // No more script packages 3290 } 3291 3292 return xScriptPackage; 3293 } 3294 3295 Reference< deployment::XPackage > ScriptSubPackageIterator::implDetectScriptPackage ( const Reference< deployment::XPackage >& rPackage, 3296 bool& rbPureDialogLib ) 3297 { 3298 Reference< deployment::XPackage > xScriptPackage; 3299 3300 if( rPackage.is() ) 3301 { 3302 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = rPackage->getPackageType(); 3303 OUString aMediaType = xPackageTypeInfo->getMediaType(); 3304 if ( aMediaType == sBasicLibMediaType ) 3305 { 3306 xScriptPackage = rPackage; 3307 } 3308 else if ( aMediaType == sDialogLibMediaType ) 3309 { 3310 rbPureDialogLib = true; 3311 xScriptPackage = rPackage; 3312 } 3313 } 3314 3315 return xScriptPackage; 3316 } 3317 3318 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextUserScriptPackage( bool& rbPureDialogLib ) 3319 { 3320 Reference< deployment::XPackage > xScriptPackage; 3321 3322 if( !m_bUserPackagesLoaded ) 3323 { 3324 try 3325 { 3326 Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext ); 3327 m_aUserPackagesSeq = xManager->getDeployedExtensions("user", 3328 Reference< task::XAbortChannel >(), 3329 Reference< ucb::XCommandEnvironment >() ); 3330 } 3331 catch(const css::uno::DeploymentException& ) 3332 { 3333 // Special Office installations may not contain deployment code 3334 m_eState = END_REACHED; 3335 return xScriptPackage; 3336 } 3337 3338 m_bUserPackagesLoaded = true; 3339 } 3340 3341 if( m_iUserPackage == m_aUserPackagesSeq.getLength() ) 3342 { 3343 m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE 3344 } 3345 else 3346 { 3347 if( m_pScriptSubPackageIterator == nullptr ) 3348 { 3349 const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray(); 3350 Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage ]; 3351 SAL_WARN_IF( 3352 !xPackage.is(), "basic", 3353 ("ScriptExtensionIterator::implGetNextUserScriptPackage():" 3354 " Invalid package")); 3355 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage ); 3356 } 3357 3358 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib ); 3359 if( !xScriptPackage.is() ) 3360 { 3361 delete m_pScriptSubPackageIterator; 3362 m_pScriptSubPackageIterator = nullptr; 3363 m_iUserPackage++; 3364 } 3365 } 3366 3367 return xScriptPackage; 3368 } 3369 3370 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextSharedScriptPackage( bool& rbPureDialogLib ) 3371 { 3372 Reference< deployment::XPackage > xScriptPackage; 3373 3374 if( !m_bSharedPackagesLoaded ) 3375 { 3376 try 3377 { 3378 Reference< XExtensionManager > xSharedManager = ExtensionManager::get( m_xContext ); 3379 m_aSharedPackagesSeq = xSharedManager->getDeployedExtensions("shared", 3380 Reference< task::XAbortChannel >(), 3381 Reference< ucb::XCommandEnvironment >() ); 3382 } 3383 catch(const css::uno::DeploymentException& ) 3384 { 3385 // Special Office installations may not contain deployment code 3386 return xScriptPackage; 3387 } 3388 3389 m_bSharedPackagesLoaded = true; 3390 } 3391 3392 if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() ) 3393 { 3394 m_eState = BUNDLED_EXTENSIONS; 3395 } 3396 else 3397 { 3398 if( m_pScriptSubPackageIterator == nullptr ) 3399 { 3400 const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray(); 3401 Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage ]; 3402 SAL_WARN_IF( 3403 !xPackage.is(), "basic", 3404 ("ScriptExtensionIterator::implGetNextSharedScriptPackage():" 3405 " Invalid package")); 3406 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage ); 3407 } 3408 3409 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib ); 3410 if( !xScriptPackage.is() ) 3411 { 3412 delete m_pScriptSubPackageIterator; 3413 m_pScriptSubPackageIterator = nullptr; 3414 m_iSharedPackage++; 3415 } 3416 } 3417 3418 return xScriptPackage; 3419 } 3420 3421 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextBundledScriptPackage( bool& rbPureDialogLib ) 3422 { 3423 Reference< deployment::XPackage > xScriptPackage; 3424 3425 if( !m_bBundledPackagesLoaded ) 3426 { 3427 try 3428 { 3429 Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext ); 3430 m_aBundledPackagesSeq = xManager->getDeployedExtensions("bundled", 3431 Reference< task::XAbortChannel >(), 3432 Reference< ucb::XCommandEnvironment >() ); 3433 } 3434 catch(const css::uno::DeploymentException& ) 3435 { 3436 // Special Office installations may not contain deployment code 3437 return xScriptPackage; 3438 } 3439 3440 m_bBundledPackagesLoaded = true; 3441 } 3442 3443 if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() ) 3444 { 3445 m_eState = END_REACHED; 3446 } 3447 else 3448 { 3449 if( m_pScriptSubPackageIterator == nullptr ) 3450 { 3451 const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray(); 3452 Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage ]; 3453 SAL_WARN_IF( 3454 !xPackage.is(), "basic", 3455 ("ScriptExtensionIterator::implGetNextBundledScriptPackage():" 3456 " Invalid package")); 3457 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage ); 3458 } 3459 3460 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib ); 3461 if( !xScriptPackage.is() ) 3462 { 3463 delete m_pScriptSubPackageIterator; 3464 m_pScriptSubPackageIterator = nullptr; 3465 m_iBundledPackage++; 3466 } 3467 } 3468 3469 return xScriptPackage; 3470 } 3471 3472 } // namespace basic 3473 3474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 3475
