nss: upgrade to release 3.73
[LibreOffice.git] / basic / source / uno / namecont.cxx
blobec112b466f3fe4d9a68abe03c5b74e2e2cb4a53c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_extensions.h>
21 #include <config_folders.h>
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 <sal/log.hxx>
37 #include <sot/storage.hxx>
38 #include <comphelper/getexpandeduri.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <comphelper/sequence.hxx>
42 #include <namecont.hxx>
43 #include <basic/basicmanagerrepository.hxx>
44 #include <tools/diagnose_ex.h>
45 #include <tools/urlobj.hxx>
46 #include <unotools/pathoptions.hxx>
47 #include <svtools/sfxecode.hxx>
48 #include <svtools/ehdl.hxx>
49 #include <basic/basmgr.hxx>
50 #include <com/sun/star/xml/sax/Parser.hpp>
51 #include <com/sun/star/xml/sax/InputSource.hpp>
52 #include <com/sun/star/io/XOutputStream.hpp>
53 #include <com/sun/star/xml/sax/Writer.hpp>
54 #include <com/sun/star/io/XInputStream.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #include <com/sun/star/uno/DeploymentException.hpp>
57 #include <com/sun/star/lang/DisposedException.hpp>
58 #include <com/sun/star/script/LibraryNotLoadedException.hpp>
59 #include <com/sun/star/script/vba/VBAScriptEventId.hpp>
60 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
61 #include <com/sun/star/util/PathSubstitution.hpp>
62 #include <com/sun/star/deployment/ExtensionManager.hpp>
63 #include <comphelper/storagehelper.hxx>
64 #include <cppuhelper/exc_hlp.hxx>
65 #include <cppuhelper/queryinterface.hxx>
66 #include <cppuhelper/supportsservice.hxx>
67 #include <cppuhelper/typeprovider.hxx>
68 #include <memory>
70 namespace basic
73 using namespace com::sun::star::document;
74 using namespace com::sun::star::container;
75 using namespace com::sun::star::uno;
76 using namespace com::sun::star::lang;
77 using namespace com::sun::star::io;
78 using namespace com::sun::star::ucb;
79 using namespace com::sun::star::script;
80 using namespace com::sun::star::beans;
81 using namespace com::sun::star::xml::sax;
82 using namespace com::sun::star::util;
83 using namespace com::sun::star::task;
84 using namespace com::sun::star::embed;
85 using namespace com::sun::star::frame;
86 using namespace com::sun::star::deployment;
87 using namespace com::sun::star;
88 using namespace cppu;
89 using namespace osl;
91 using com::sun::star::uno::Reference;
93 // #i34411: Flag for error handling during migration
94 static bool GbMigrationSuppressErrors = false;
97 // Implementation class NameContainer
99 // Methods XElementAccess
100 Type NameContainer::getElementType()
102 return mType;
105 sal_Bool NameContainer::hasElements()
107 bool bRet = (mnElementCount > 0);
108 return bRet;
111 // Methods XNameAccess
112 Any NameContainer::getByName( const OUString& aName )
114 NameContainerNameMap::iterator aIt = mHashMap.find( aName );
115 if( aIt == mHashMap.end() )
117 throw NoSuchElementException();
119 sal_Int32 iHashResult = (*aIt).second;
120 Any aRetAny = mValues[ iHashResult ];
121 return aRetAny;
124 Sequence< OUString > NameContainer::getElementNames()
126 return comphelper::containerToSequence(mNames);
129 sal_Bool NameContainer::hasByName( const OUString& aName )
131 NameContainerNameMap::iterator aIt = mHashMap.find( aName );
132 bool bRet = ( aIt != mHashMap.end() );
133 return bRet;
137 // Methods XNameReplace
138 void NameContainer::replaceByName( const OUString& aName, const Any& aElement )
140 const Type& aAnyType = aElement.getValueType();
141 if( mType != aAnyType )
143 throw IllegalArgumentException();
145 NameContainerNameMap::iterator aIt = mHashMap.find( aName );
146 if( aIt == mHashMap.end() )
148 throw NoSuchElementException();
150 sal_Int32 iHashResult = (*aIt).second;
151 Any aOldElement = mValues[ iHashResult ];
152 mValues[ iHashResult ] = aElement;
155 // Fire event
156 if( maContainerListeners.getLength() > 0 )
158 ContainerEvent aEvent;
159 aEvent.Source = mpxEventSource;
160 aEvent.Accessor <<= aName;
161 aEvent.Element = aElement;
162 aEvent.ReplacedElement = aOldElement;
163 maContainerListeners.notifyEach( &XContainerListener::elementReplaced, aEvent );
166 /* After the container event has been fired (one listener will update the
167 core Basic manager), fire change event. Listeners can rely on that the
168 Basic source code of the core Basic manager is up-to-date. */
169 if( maChangesListeners.getLength() > 0 )
171 ChangesEvent aEvent;
172 aEvent.Source = mpxEventSource;
173 aEvent.Base <<= aEvent.Source;
174 aEvent.Changes.realloc( 1 );
175 aEvent.Changes[ 0 ].Accessor <<= aName;
176 aEvent.Changes[ 0 ].Element = aElement;
177 aEvent.Changes[ 0 ].ReplacedElement = aOldElement;
178 maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent );
182 void NameContainer::insertCheck(const OUString& aName, const Any& aElement)
184 NameContainerNameMap::iterator aIt = mHashMap.find(aName);
185 if( aIt != mHashMap.end() )
187 throw ElementExistException();
189 insertNoCheck(aName, aElement);
192 void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement)
194 const Type& aAnyType = aElement.getValueType();
195 if( mType != aAnyType )
197 throw IllegalArgumentException();
200 sal_Int32 nCount = mNames.size();
201 mNames.push_back( aName );
202 mValues.push_back( aElement );
204 mHashMap[ aName ] = nCount;
205 mnElementCount++;
207 // Fire event
208 if( maContainerListeners.getLength() > 0 )
210 ContainerEvent aEvent;
211 aEvent.Source = mpxEventSource;
212 aEvent.Accessor <<= aName;
213 aEvent.Element = aElement;
214 maContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
217 /* After the container event has been fired (one listener will update the
218 core Basic manager), fire change event. Listeners can rely on that the
219 Basic source code of the core Basic manager is up-to-date. */
220 if( maChangesListeners.getLength() > 0 )
222 ChangesEvent aEvent;
223 aEvent.Source = mpxEventSource;
224 aEvent.Base <<= aEvent.Source;
225 aEvent.Changes.realloc( 1 );
226 aEvent.Changes[ 0 ].Accessor <<= aName;
227 aEvent.Changes[ 0 ].Element = aElement;
228 maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent );
232 // Methods XNameContainer
233 void NameContainer::insertByName( const OUString& aName, const Any& aElement )
235 insertCheck(aName, aElement);
238 void NameContainer::removeByName( const OUString& aName )
240 NameContainerNameMap::iterator aIt = mHashMap.find( aName );
241 if( aIt == mHashMap.end() )
243 OUString sMessage = "\"" + aName + "\" not found";
244 throw NoSuchElementException(sMessage);
247 sal_Int32 iHashResult = (*aIt).second;
248 Any aOldElement = mValues[ iHashResult ];
249 mHashMap.erase( aIt );
250 sal_Int32 iLast = mNames.size() - 1;
251 if( iLast != iHashResult )
253 mNames[ iHashResult ] = mNames[ iLast ];
254 mValues[ iHashResult ] = mValues[ iLast ];
255 mHashMap[ mNames[ iHashResult ] ] = iHashResult;
257 mNames.resize( iLast );
258 mValues.resize( iLast );
259 mnElementCount--;
261 // Fire event
262 if( maContainerListeners.getLength() > 0 )
264 ContainerEvent aEvent;
265 aEvent.Source = mpxEventSource;
266 aEvent.Accessor <<= aName;
267 aEvent.Element = aOldElement;
268 maContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
271 /* After the container event has been fired (one listener will update the
272 core Basic manager), fire change event. Listeners can rely on that the
273 Basic source code of the core Basic manager is up-to-date. */
274 if( maChangesListeners.getLength() > 0 )
276 ChangesEvent aEvent;
277 aEvent.Source = mpxEventSource;
278 aEvent.Base <<= aEvent.Source;
279 aEvent.Changes.realloc( 1 );
280 aEvent.Changes[ 0 ].Accessor <<= aName;
281 // aEvent.Changes[ 0 ].Element remains empty (meaning "replaced with nothing")
282 aEvent.Changes[ 0 ].ReplacedElement = aOldElement;
283 maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent );
288 // Methods XContainer
289 void SAL_CALL NameContainer::addContainerListener( const Reference< XContainerListener >& xListener )
291 if( !xListener.is() )
293 throw RuntimeException("addContainerListener called with null xListener");
295 maContainerListeners.addInterface( Reference<XInterface>(xListener, UNO_QUERY) );
298 void SAL_CALL NameContainer::removeContainerListener( const Reference< XContainerListener >& xListener )
300 if( !xListener.is() )
302 throw RuntimeException("removeContainerListener called with null xListener");
304 maContainerListeners.removeInterface( Reference<XInterface>(xListener, UNO_QUERY) );
307 // Methods XChangesNotifier
308 void SAL_CALL NameContainer::addChangesListener( const Reference< XChangesListener >& xListener )
310 if( !xListener.is() )
312 throw RuntimeException("addChangesListener called with null xListener");
314 maChangesListeners.addInterface( Reference<XInterface>(xListener, UNO_QUERY) );
317 void SAL_CALL NameContainer::removeChangesListener( const Reference< XChangesListener >& xListener )
319 if( !xListener.is() )
321 throw RuntimeException("removeChangesListener called with null xListener");
323 maChangesListeners.removeInterface( Reference<XInterface>(xListener, UNO_QUERY) );
327 // ModifiableHelper
329 void ModifiableHelper::setModified( bool _bModified )
331 if ( _bModified == mbModified )
333 return;
335 mbModified = _bModified;
337 if ( m_aModifyListeners.getLength() == 0 )
339 return;
341 EventObject aModifyEvent( m_rEventSource );
342 m_aModifyListeners.notifyEach( &XModifyListener::modified, aModifyEvent );
346 VBAScriptListenerContainer::VBAScriptListenerContainer( ::osl::Mutex& rMutex ) :
347 VBAScriptListenerContainer_BASE( rMutex )
351 bool VBAScriptListenerContainer::implTypedNotify( const Reference< vba::XVBAScriptListener >& rxListener, const vba::VBAScriptEvent& rEvent )
353 rxListener->notifyVBAScriptEvent( rEvent );
354 return true; // notify all other listeners too
357 // Ctor
358 SfxLibraryContainer::SfxLibraryContainer()
359 : SfxLibraryContainer_BASE( m_aMutex )
360 , maVBAScriptListeners( m_aMutex )
361 , mnRunningVBAScripts( 0 )
362 , mbVBACompat( false )
363 , maModifiable( *this, m_aMutex )
364 , maNameContainer( new NameContainer(cppu::UnoType<XNameAccess>::get()) )
365 , mbOldInfoFormat( false )
366 , mbOasis2OOoFormat( false )
367 , mpBasMgr( nullptr )
368 , mbOwnBasMgr( false )
369 , meInitMode(DEFAULT)
371 mxContext = comphelper::getProcessComponentContext();
373 mxSFI = ucb::SimpleFileAccess::create( mxContext );
375 mxStringSubstitution = util::PathSubstitution::create( mxContext );
378 SfxLibraryContainer::~SfxLibraryContainer()
380 if( mbOwnBasMgr )
382 delete mpBasMgr;
386 void SfxLibraryContainer::enterMethod()
388 Application::GetSolarMutex().acquire();
389 if ( rBHelper.bInDispose || rBHelper.bDisposed )
391 throw DisposedException( OUString(), *this );
395 void SfxLibraryContainer::leaveMethod()
397 Application::GetSolarMutex().release();
400 BasicManager* SfxLibraryContainer::getBasicManager()
404 if ( mpBasMgr )
406 return mpBasMgr;
408 Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY );
409 SAL_WARN_IF(
410 !xDocument.is(), "basic",
411 ("SfxLibraryContainer::getBasicManager: cannot obtain a BasicManager"
412 " without document!"));
413 if ( xDocument.is() )
415 mpBasMgr = BasicManagerRepository::getDocumentBasicManager( xDocument );
418 catch (const css::ucb::ContentCreationException&)
420 TOOLS_WARN_EXCEPTION( "basic", "SfxLibraryContainer::getBasicManager:" );
422 return mpBasMgr;
425 // Methods XStorageBasedLibraryContainer
426 Reference< XStorage > SAL_CALL SfxLibraryContainer::getRootStorage()
428 LibraryContainerMethodGuard aGuard( *this );
429 return mxStorage;
432 void SAL_CALL SfxLibraryContainer::setRootStorage( const Reference< XStorage >& _rxRootStorage )
434 LibraryContainerMethodGuard aGuard( *this );
435 if ( !_rxRootStorage.is() )
437 throw IllegalArgumentException();
439 mxStorage = _rxRootStorage;
440 onNewRootStorage();
443 void SAL_CALL SfxLibraryContainer::storeLibrariesToStorage( const Reference< XStorage >& _rxRootStorage )
445 LibraryContainerMethodGuard aGuard( *this );
446 if ( !_rxRootStorage.is() )
448 throw IllegalArgumentException();
452 storeLibraries_Impl( _rxRootStorage, true );
454 catch( const Exception& )
456 throw WrappedTargetException( OUString(),
457 *this, ::cppu::getCaughtException() );
462 // Methods XModifiable
463 sal_Bool SfxLibraryContainer::isModified()
465 LibraryContainerMethodGuard aGuard( *this );
466 if ( maModifiable.isModified() )
468 return true;
470 // the library container is not modified, go through the libraries and check whether they are modified
471 Sequence< OUString > aNames = maNameContainer->getElementNames();
472 const OUString* pNames = aNames.getConstArray();
473 sal_Int32 nNameCount = aNames.getLength();
475 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
477 OUString aName = pNames[ i ];
480 SfxLibrary* pImplLib = getImplLib( aName );
481 if( pImplLib->isModified() )
483 if ( aName == "Standard" )
485 // this is a workaround that has to be implemented because
486 // empty standard library should stay marked as modified
487 // but should not be treated as modified while it is empty
488 if ( pImplLib->hasElements() )
489 return true;
491 else
493 return true;
497 catch(const css::container::NoSuchElementException&)
502 return false;
505 void SAL_CALL SfxLibraryContainer::setModified( sal_Bool _bModified )
507 LibraryContainerMethodGuard aGuard( *this );
508 maModifiable.setModified( _bModified );
511 void SAL_CALL SfxLibraryContainer::addModifyListener( const Reference< XModifyListener >& _rxListener )
513 LibraryContainerMethodGuard aGuard( *this );
514 maModifiable.addModifyListener( _rxListener );
517 void SAL_CALL SfxLibraryContainer::removeModifyListener( const Reference< XModifyListener >& _rxListener )
519 LibraryContainerMethodGuard aGuard( *this );
520 maModifiable.removeModifyListener( _rxListener );
523 // Methods XPersistentLibraryContainer
524 Any SAL_CALL SfxLibraryContainer::getRootLocation()
526 LibraryContainerMethodGuard aGuard( *this );
527 return Any( getRootStorage() );
530 OUString SAL_CALL SfxLibraryContainer::getContainerLocationName()
532 LibraryContainerMethodGuard aGuard( *this );
533 return maLibrariesDir;
536 void SAL_CALL SfxLibraryContainer::storeLibraries( )
538 LibraryContainerMethodGuard aGuard( *this );
541 storeLibraries_Impl( mxStorage, mxStorage.is() );
542 // we need to store *all* libraries if and only if we are based on a storage:
543 // in this case, storeLibraries_Impl will remove the source storage, after loading
544 // all libraries, so we need to force them to be stored, again
546 catch( const Exception& )
548 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
552 static void checkAndCopyFileImpl( const INetURLObject& rSourceFolderInetObj,
553 const INetURLObject& rTargetFolderInetObj,
554 const OUString& rCheckFileName,
555 const OUString& rCheckExtension,
556 const Reference< XSimpleFileAccess3 >& xSFI )
558 INetURLObject aTargetFolderInetObj( rTargetFolderInetObj );
559 aTargetFolderInetObj.insertName( rCheckFileName, true, INetURLObject::LAST_SEGMENT,
560 INetURLObject::EncodeMechanism::All );
561 aTargetFolderInetObj.setExtension( rCheckExtension );
562 OUString aTargetFile = aTargetFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
563 if( !xSFI->exists( aTargetFile ) )
565 INetURLObject aSourceFolderInetObj( rSourceFolderInetObj );
566 aSourceFolderInetObj.insertName( rCheckFileName, true, INetURLObject::LAST_SEGMENT,
567 INetURLObject::EncodeMechanism::All );
568 aSourceFolderInetObj.setExtension( rCheckExtension );
569 OUString aSourceFile = aSourceFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
570 xSFI->copy( aSourceFile, aTargetFile );
574 static void createVariableURL( OUString& rStr, const OUString& rLibName,
575 const OUString& rInfoFileName, bool bUser )
577 if( bUser )
579 rStr = "$(USER)/basic/";
581 else
583 rStr = "$(INST)/" LIBO_SHARE_FOLDER "/basic/";
585 rStr += rLibName + "/" + rInfoFileName + ".xlb/";
588 void SfxLibraryContainer::init( const OUString& rInitialDocumentURL, const uno::Reference< embed::XStorage >& rxInitialStorage )
590 // this might be called from within the ctor, and the impl_init might (indirectly) create
591 // a UNO reference to ourself.
592 // Ensure that we're not destroyed while we're in here
593 osl_atomic_increment( &m_refCount );
594 init_Impl( rInitialDocumentURL, rxInitialStorage );
595 osl_atomic_decrement( &m_refCount );
598 void SfxLibraryContainer::init_Impl( const OUString& rInitialDocumentURL,
599 const uno::Reference< embed::XStorage >& rxInitialStorage )
601 uno::Reference< embed::XStorage > xStorage = rxInitialStorage;
603 maInitialDocumentURL = rInitialDocumentURL;
604 maInfoFileName = OUString::createFromAscii( getInfoFileName() );
605 maOldInfoFileName = OUString::createFromAscii( getOldInfoFileName() );
606 maLibElementFileExtension = OUString::createFromAscii( getLibElementFileExtension() );
607 maLibrariesDir = OUString::createFromAscii( getLibrariesDir() );
609 meInitMode = DEFAULT;
610 INetURLObject aInitUrlInetObj( maInitialDocumentURL );
611 OUString aInitFileName = aInitUrlInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
612 if( !aInitFileName.isEmpty() )
614 // We need a BasicManager to avoid problems
615 StarBASIC* pBas = new StarBASIC();
616 mpBasMgr = new BasicManager( pBas );
617 mbOwnBasMgr = true;
619 OUString aExtension = aInitUrlInetObj.getExtension();
620 if( aExtension == "xlc" )
622 meInitMode = CONTAINER_INIT_FILE;
623 INetURLObject aLibPathInetObj( aInitUrlInetObj );
624 aLibPathInetObj.removeSegment();
625 maLibraryPath = aLibPathInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
627 else if( aExtension == "xlb" )
629 meInitMode = LIBRARY_INIT_FILE;
630 uno::Reference< embed::XStorage > xDummyStor;
631 ::xmlscript::LibDescriptor aLibDesc;
632 implLoadLibraryIndexFile( nullptr, aLibDesc, xDummyStor, aInitFileName );
633 return;
635 else
637 // Decide between old and new document
638 bool bOldStorage = SotStorage::IsOLEStorage( aInitFileName );
639 if ( bOldStorage )
641 meInitMode = OLD_BASIC_STORAGE;
642 importFromOldStorage( aInitFileName );
643 return;
645 else
647 meInitMode = OFFICE_DOCUMENT;
650 xStorage = ::comphelper::OStorageHelper::GetStorageFromURL( aInitFileName, embed::ElementModes::READ );
652 catch (const uno::Exception& )
654 // TODO: error handling
659 else
661 // Default paths
662 maLibraryPath = SvtPathOptions().GetBasicPath();
665 Reference< XParser > xParser = xml::sax::Parser::create(mxContext);
667 uno::Reference< io::XInputStream > xInput;
669 mxStorage = xStorage;
670 bool bStorage = mxStorage.is();
673 // #110009: Scope to force the StorageRefs to be destructed and
674 // so the streams to be closed before the preload operation
677 uno::Reference< embed::XStorage > xLibrariesStor;
678 OUString aFileName;
680 int nPassCount = 1;
681 if( !bStorage && meInitMode == DEFAULT )
683 nPassCount = 2;
685 for( int nPass = 0 ; nPass < nPassCount ; nPass++ )
687 if( bStorage )
689 SAL_WARN_IF(
690 meInitMode != DEFAULT && meInitMode != OFFICE_DOCUMENT, "basic",
691 "Wrong InitMode for document");
694 uno::Reference< io::XStream > xStream;
695 xLibrariesStor = xStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
697 if ( xLibrariesStor.is() )
699 aFileName = maInfoFileName + "-lc.xml";
702 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
704 catch(const uno::Exception& )
707 if( !xStream.is() )
709 mbOldInfoFormat = true;
711 // Check old version
712 aFileName = maOldInfoFileName + ".xml";
715 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
717 catch(const uno::Exception& )
720 if( !xStream.is() )
722 // Check for EA2 document version with wrong extensions
723 aFileName = maOldInfoFileName + ".xli";
724 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
729 if ( xStream.is() )
731 xInput = xStream->getInputStream();
734 catch(const uno::Exception& )
736 // TODO: error handling?
739 else
741 std::unique_ptr<INetURLObject> pLibInfoInetObj;
742 if( meInitMode == CONTAINER_INIT_FILE )
744 aFileName = aInitFileName;
746 else
748 if( nPass == 1 )
750 pLibInfoInetObj.reset(new INetURLObject( maLibraryPath.getToken(0, ';') ));
752 else
754 pLibInfoInetObj.reset(new INetURLObject( maLibraryPath.getToken(1, ';') ));
756 pLibInfoInetObj->insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
757 pLibInfoInetObj->setExtension( "xlc" );
758 aFileName = pLibInfoInetObj->GetMainURL( INetURLObject::DecodeMechanism::NONE );
763 xInput = mxSFI->openFileRead( aFileName );
765 catch(const Exception& )
767 // Silently tolerate empty or missing files
768 xInput.clear();
771 // Old variant?
772 if( !xInput.is() && nPass == 0 )
774 INetURLObject aLibInfoInetObj( maLibraryPath.getToken(1, ';') );
775 aLibInfoInetObj.insertName( maOldInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
776 aLibInfoInetObj.setExtension( "xli" );
777 aFileName = aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
781 xInput = mxSFI->openFileRead( aFileName );
782 mbOldInfoFormat = true;
784 catch(const Exception& )
786 xInput.clear();
791 if( xInput.is() )
793 InputSource source;
794 source.aInputStream = xInput;
795 source.sSystemId = aFileName;
797 // start parsing
798 auto pLibArray = std::make_unique<::xmlscript::LibDescriptorArray> ( );
802 xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( pLibArray.get() ) );
803 xParser->parseStream( source );
805 catch ( const xml::sax::SAXException& )
807 TOOLS_WARN_EXCEPTION( "basic", "" );
808 return;
810 catch ( const io::IOException& )
812 TOOLS_WARN_EXCEPTION( "basic", "" );
813 return;
816 sal_Int32 nLibCount = pLibArray->mnLibCount;
817 for( sal_Int32 i = 0 ; i < nLibCount ; i++ )
819 ::xmlscript::LibDescriptor& rLib = pLibArray->mpLibs[i];
821 // Check storage URL
822 OUString aStorageURL = rLib.aStorageURL;
823 if( !bStorage && aStorageURL.isEmpty() && nPass == 0 )
825 OUString aLibraryPath;
826 if( meInitMode == CONTAINER_INIT_FILE )
828 aLibraryPath = maLibraryPath;
830 else
832 aLibraryPath = maLibraryPath.getToken(1, ';');
834 INetURLObject aInetObj( aLibraryPath );
836 aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT,
837 INetURLObject::EncodeMechanism::All );
838 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
839 if( mxSFI->isFolder( aLibDirPath ) )
841 createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, true );
842 maModifiable.setModified( true );
844 else if( rLib.bLink )
846 // Check "share" path
847 INetURLObject aShareInetObj( maLibraryPath.getToken(0, ';') );
848 aShareInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT,
849 INetURLObject::EncodeMechanism::All );
850 OUString aShareLibDirPath = aShareInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
851 if( mxSFI->isFolder( aShareLibDirPath ) )
853 createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, false );
854 maModifiable.setModified( true );
856 else
858 // #i25537: Ignore lib if library folder does not really exist
859 continue;
864 OUString aLibName = rLib.aName;
866 // If the same library name is used by the shared and the
867 // user lib container index files the user file wins
868 if( nPass == 1 && hasByName( aLibName ) )
870 continue;
872 SfxLibrary* pImplLib;
873 if( rLib.bLink )
875 Reference< XNameAccess > xLib =
876 createLibraryLink( aLibName, rLib.aStorageURL, rLib.bReadOnly );
877 pImplLib = static_cast< SfxLibrary* >( xLib.get() );
879 else
881 Reference< XNameContainer > xLib = createLibrary( aLibName );
882 pImplLib = static_cast< SfxLibrary* >( xLib.get() );
883 pImplLib->mbLoaded = false;
884 pImplLib->mbReadOnly = rLib.bReadOnly;
885 if( !bStorage )
887 checkStorageURL( rLib.aStorageURL, pImplLib->maLibInfoFileURL,
888 pImplLib->maStorageURL, pImplLib->maUnexpandedStorageURL );
891 maModifiable.setModified( false );
893 // Read library info files
894 if( !mbOldInfoFormat )
896 uno::Reference< embed::XStorage > xLibraryStor;
897 if( !pImplLib->mbInitialised && bStorage )
901 xLibraryStor = xLibrariesStor->openStorageElement( rLib.aName,
902 embed::ElementModes::READ );
904 catch(const uno::Exception& )
906 #if OSL_DEBUG_LEVEL > 0
907 TOOLS_WARN_EXCEPTION(
908 "basic",
909 "couldn't open sub storage for library \"" << rLib.aName << "\"");
910 #endif
914 // Link is already initialised in createLibraryLink()
915 if( !pImplLib->mbInitialised && (!bStorage || xLibraryStor.is()) )
917 bool bLoaded = implLoadLibraryIndexFile( pImplLib, rLib, xLibraryStor, OUString() );
918 SAL_WARN_IF(
919 bLoaded && aLibName != rLib.aName, "basic",
920 ("Different library names in library container and"
921 " library info files!"));
922 if( GbMigrationSuppressErrors && !bLoaded )
924 removeLibrary( aLibName );
928 else if( !bStorage )
930 // Write new index file immediately because otherwise
931 // the library elements will be lost when storing into
932 // the new info format
933 uno::Reference< embed::XStorage > xTmpStorage;
934 implStoreLibraryIndexFile( pImplLib, rLib, xTmpStorage );
937 implImportLibDescriptor( pImplLib, rLib );
939 if( nPass == 1 )
941 pImplLib->mbSharedIndexFile = true;
942 pImplLib->mbReadOnly = true;
946 // Keep flag for documents to force writing the new index files
947 if( !bStorage )
949 mbOldInfoFormat = false;
954 // #110009: END Scope to force the StorageRefs to be destructed
957 if( !bStorage && meInitMode == DEFAULT )
961 implScanExtensions();
963 catch(const uno::Exception& )
965 // TODO: error handling?
966 SAL_WARN("basic", "Cannot access extensions!");
970 // Preload?
972 Sequence< OUString > aNames = maNameContainer->getElementNames();
973 const OUString* pNames = aNames.getConstArray();
974 sal_Int32 nNameCount = aNames.getLength();
975 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
977 OUString aName = pNames[ i ];
978 SfxLibrary* pImplLib = getImplLib( aName );
979 if( pImplLib->mbPreload )
981 loadLibrary( aName );
986 if( meInitMode != DEFAULT )
987 return;
989 INetURLObject aUserBasicInetObj( maLibraryPath.getToken(1, ';') );
990 OUString aStandardStr("Standard");
992 INetURLObject aPrevUserBasicInetObj_1( aUserBasicInetObj );
993 aPrevUserBasicInetObj_1.removeSegment();
994 INetURLObject aPrevUserBasicInetObj_2 = aPrevUserBasicInetObj_1;
995 aPrevUserBasicInetObj_1.Append( "__basic_80" );
996 aPrevUserBasicInetObj_2.Append( "__basic_80_2" );
998 // #i93163
999 bool bCleanUp = false;
1002 INetURLObject aPrevUserBasicInetObj = aPrevUserBasicInetObj_1;
1003 OUString aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1004 if( mxSFI->isFolder( aPrevFolder ) )
1006 // Check if Standard folder exists and is complete
1007 INetURLObject aUserBasicStandardInetObj( aUserBasicInetObj );
1008 aUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT,
1009 INetURLObject::EncodeMechanism::All );
1010 INetURLObject aPrevUserBasicStandardInetObj( aPrevUserBasicInetObj );
1011 aPrevUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT,
1012 INetURLObject::EncodeMechanism::All );
1013 OUString aPrevStandardFolder = aPrevUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1014 if( mxSFI->isFolder( aPrevStandardFolder ) )
1016 OUString aXlbExtension( "xlb" );
1017 OUString aCheckFileName;
1019 // Check if script.xlb exists
1020 aCheckFileName = "script";
1021 checkAndCopyFileImpl( aUserBasicStandardInetObj,
1022 aPrevUserBasicStandardInetObj,
1023 aCheckFileName, aXlbExtension, mxSFI );
1025 // Check if dialog.xlb exists
1026 aCheckFileName = "dialog";
1027 checkAndCopyFileImpl( aUserBasicStandardInetObj,
1028 aPrevUserBasicStandardInetObj,
1029 aCheckFileName, aXlbExtension, mxSFI );
1031 // Check if module1.xba exists
1032 aCheckFileName = "Module1";
1033 checkAndCopyFileImpl( aUserBasicStandardInetObj,
1034 aPrevUserBasicStandardInetObj,
1035 aCheckFileName, "xba", mxSFI );
1037 else
1039 OUString aStandardFolder = aUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1040 mxSFI->copy( aStandardFolder, aPrevStandardFolder );
1043 OUString aPrevCopyToFolder = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1044 mxSFI->copy( aPrevFolder, aPrevCopyToFolder );
1046 else
1048 aPrevUserBasicInetObj = aPrevUserBasicInetObj_2;
1049 aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1051 if( mxSFI->isFolder( aPrevFolder ) )
1053 rtl::Reference<SfxLibraryContainer> pPrevCont = createInstanceImpl();
1055 // Rename previous basic folder to make storage URLs correct during initialisation
1056 OUString aFolderUserBasic = aUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1057 INetURLObject aUserBasicTmpInetObj( aUserBasicInetObj );
1058 aUserBasicTmpInetObj.removeSegment();
1059 aUserBasicTmpInetObj.Append( "__basic_tmp" );
1060 OUString aFolderTmp = aUserBasicTmpInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1062 mxSFI->move( aFolderUserBasic, aFolderTmp );
1065 mxSFI->move( aPrevFolder, aFolderUserBasic );
1067 catch(const Exception& )
1069 // Move back user/basic folder
1072 mxSFI->kill( aFolderUserBasic );
1074 catch(const Exception& )
1076 mxSFI->move( aFolderTmp, aFolderUserBasic );
1077 throw;
1080 INetURLObject aPrevUserBasicLibInfoInetObj( aUserBasicInetObj );
1081 aPrevUserBasicLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT,
1082 INetURLObject::EncodeMechanism::All );
1083 aPrevUserBasicLibInfoInetObj.setExtension( "xlc");
1084 OUString aLibInfoFileName = aPrevUserBasicLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1085 Sequence<Any> aInitSeq( 1 );
1086 aInitSeq.getArray()[0] <<= aLibInfoFileName;
1087 GbMigrationSuppressErrors = true;
1088 pPrevCont->initialize( aInitSeq );
1089 GbMigrationSuppressErrors = false;
1091 // Rename folders back
1092 mxSFI->move( aFolderUserBasic, aPrevFolder );
1093 mxSFI->move( aFolderTmp, aFolderUserBasic );
1095 Sequence< OUString > aNames = pPrevCont->getElementNames();
1096 const OUString* pNames = aNames.getConstArray();
1097 sal_Int32 nNameCount = aNames.getLength();
1099 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1101 OUString aLibName = pNames[ i ];
1102 if( hasByName( aLibName ) )
1104 if( aLibName == aStandardStr )
1106 SfxLibrary* pImplLib = getImplLib( aStandardStr );
1107 OUString aStandardFolder = pImplLib->maStorageURL;
1108 mxSFI->kill( aStandardFolder );
1110 else
1112 continue;
1116 SfxLibrary* pImplLib = pPrevCont->getImplLib( aLibName );
1117 if( pImplLib->mbLink )
1119 OUString aStorageURL = pImplLib->maUnexpandedStorageURL;
1120 bool bCreateLink = true;
1121 if( aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 ||
1122 aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1 ||
1123 aStorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 ||
1124 aStorageURL.indexOf( "$(INST)" ) != -1 )
1126 bCreateLink = false;
1128 if( bCreateLink )
1130 createLibraryLink( aLibName, pImplLib->maStorageURL, pImplLib->mbReadOnly );
1133 else
1135 // Move folder if not already done
1136 INetURLObject aUserBasicLibFolderInetObj( aUserBasicInetObj );
1137 aUserBasicLibFolderInetObj.Append( aLibName );
1138 OUString aLibFolder = aUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1140 INetURLObject aPrevUserBasicLibFolderInetObj( aPrevUserBasicInetObj );
1141 aPrevUserBasicLibFolderInetObj.Append( aLibName );
1142 OUString aPrevLibFolder = aPrevUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1144 if( mxSFI->isFolder( aPrevLibFolder ) && !mxSFI->isFolder( aLibFolder ) )
1146 mxSFI->move( aPrevLibFolder, aLibFolder );
1149 if( aLibName == aStandardStr )
1151 maNameContainer->removeByName( aLibName );
1154 // Create library
1155 Reference< XNameContainer > xLib = createLibrary( aLibName );
1156 SfxLibrary* pNewLib = static_cast< SfxLibrary* >( xLib.get() );
1157 pNewLib->mbLoaded = false;
1158 pNewLib->implSetModified( false );
1159 checkStorageURL( aLibFolder, pNewLib->maLibInfoFileURL,
1160 pNewLib->maStorageURL, pNewLib->maUnexpandedStorageURL );
1162 uno::Reference< embed::XStorage > xDummyStor;
1163 ::xmlscript::LibDescriptor aLibDesc;
1164 implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, pNewLib->maLibInfoFileURL );
1165 implImportLibDescriptor( pNewLib, aLibDesc );
1168 mxSFI->kill( aPrevFolder );
1171 catch(const Exception&)
1173 TOOLS_WARN_EXCEPTION("basic", "Upgrade of Basic installation failed somehow" );
1174 bCleanUp = true;
1177 // #i93163
1178 if( !bCleanUp )
1179 return;
1181 INetURLObject aPrevUserBasicInetObj_Err( aUserBasicInetObj );
1182 aPrevUserBasicInetObj_Err.removeSegment();
1183 aPrevUserBasicInetObj_Err.Append( "__basic_80_err" );
1184 OUString aPrevFolder_Err = aPrevUserBasicInetObj_Err.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1186 bool bSaved = false;
1189 OUString aPrevFolder_1 = aPrevUserBasicInetObj_1.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1190 if( mxSFI->isFolder( aPrevFolder_1 ) )
1192 mxSFI->move( aPrevFolder_1, aPrevFolder_Err );
1193 bSaved = true;
1196 catch(const Exception& )
1200 OUString aPrevFolder_2 = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1201 if( !bSaved && mxSFI->isFolder( aPrevFolder_2 ) )
1203 mxSFI->move( aPrevFolder_2, aPrevFolder_Err );
1205 else
1207 mxSFI->kill( aPrevFolder_2 );
1210 catch(const Exception& )
1214 void SfxLibraryContainer::implScanExtensions()
1216 #if HAVE_FEATURE_EXTENSIONS
1217 ScriptExtensionIterator aScriptIt;
1219 bool bPureDialogLib = false;
1220 for (;;)
1222 OUString aLibURL = aScriptIt.nextBasicOrDialogLibrary( bPureDialogLib );
1223 if (aLibURL.isEmpty())
1224 break;
1225 if( bPureDialogLib && maInfoFileName == "script" )
1227 continue;
1229 // Extract lib name
1230 sal_Int32 nLen = aLibURL.getLength();
1231 sal_Int32 indexLastSlash = aLibURL.lastIndexOf( '/' );
1232 sal_Int32 nReduceCopy = 0;
1233 if( indexLastSlash == nLen - 1 )
1235 nReduceCopy = 1;
1236 indexLastSlash = aLibURL.lastIndexOf( '/', nLen - 1 );
1239 OUString aLibName = aLibURL.copy( indexLastSlash + 1, nLen - indexLastSlash - nReduceCopy - 1 );
1241 // If a library of the same exists the existing library wins
1242 if( hasByName( aLibName ) )
1244 continue;
1246 // Add index file to URL
1247 OUString aIndexFileURL = aLibURL;
1248 if( nReduceCopy == 0 )
1250 aIndexFileURL += "/";
1252 aIndexFileURL += maInfoFileName + ".xlb";
1254 // Create link
1255 const bool bReadOnly = false;
1256 createLibraryLink( aLibName, aIndexFileURL, bReadOnly );
1258 #else
1259 (void) this;
1260 #endif
1263 // Handle maLibInfoFileURL and maStorageURL correctly
1264 void SfxLibraryContainer::checkStorageURL( const OUString& aSourceURL,
1265 OUString& aLibInfoFileURL, OUString& aStorageURL,
1266 OUString& aUnexpandedStorageURL )
1268 OUString aExpandedSourceURL = expand_url( aSourceURL );
1269 if( aExpandedSourceURL != aSourceURL )
1271 aUnexpandedStorageURL = aSourceURL;
1273 INetURLObject aInetObj( aExpandedSourceURL );
1274 OUString aExtension = aInetObj.getExtension();
1275 if( aExtension == "xlb" )
1277 // URL to xlb file
1278 aLibInfoFileURL = aExpandedSourceURL;
1279 aInetObj.removeSegment();
1280 aStorageURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1282 else
1284 // URL to library folder
1285 aStorageURL = aExpandedSourceURL;
1286 aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1287 aInetObj.setExtension( "xlb" );
1288 aLibInfoFileURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1292 SfxLibrary* SfxLibraryContainer::getImplLib( const OUString& rLibraryName )
1294 Any aLibAny = maNameContainer->getByName( rLibraryName ) ;
1295 Reference< XNameAccess > xNameAccess;
1296 aLibAny >>= xNameAccess;
1297 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
1298 return pImplLib;
1302 // Storing with password encryption
1304 // Empty implementation, avoids unnecessary implementation in dlgcont.cxx
1305 bool SfxLibraryContainer::implStorePasswordLibrary( SfxLibrary*,
1306 const OUString&,
1307 const uno::Reference< embed::XStorage >&,
1308 const uno::Reference< task::XInteractionHandler >& )
1310 return false;
1313 bool SfxLibraryContainer::implStorePasswordLibrary(
1314 SfxLibrary* /*pLib*/,
1315 const OUString& /*aName*/,
1316 const css::uno::Reference< css::embed::XStorage >& /*xStorage*/,
1317 const OUString& /*aTargetURL*/,
1318 const Reference< XSimpleFileAccess3 >& /*xToUseSFI*/,
1319 const uno::Reference< task::XInteractionHandler >& )
1321 return false;
1324 bool SfxLibraryContainer::implLoadPasswordLibrary(
1325 SfxLibrary* /*pLib*/,
1326 const OUString& /*Name*/,
1327 bool /*bVerifyPasswordOnly*/ )
1329 return true;
1332 OUString SfxLibraryContainer::createAppLibraryFolder( SfxLibrary* pLib, const OUString& aName )
1334 OUString aLibDirPath = pLib->maStorageURL;
1335 if( aLibDirPath.isEmpty() )
1337 INetURLObject aInetObj( maLibraryPath.getToken(1, ';') );
1338 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1339 checkStorageURL( aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), pLib->maLibInfoFileURL,
1340 pLib->maStorageURL, pLib->maUnexpandedStorageURL );
1341 aLibDirPath = pLib->maStorageURL;
1344 if( !mxSFI->isFolder( aLibDirPath ) )
1348 mxSFI->createFolder( aLibDirPath );
1350 catch(const Exception& )
1354 return aLibDirPath;
1357 // Storing
1358 void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib,
1359 const OUString& aName,
1360 const uno::Reference< embed::XStorage >& xStorage )
1362 Reference< XSimpleFileAccess3 > xDummySFA;
1363 Reference< XInteractionHandler > xDummyHandler;
1364 implStoreLibrary( pLib, aName, xStorage, OUString(), xDummySFA, xDummyHandler );
1367 // New variant for library export
1368 void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib,
1369 const OUString& aName,
1370 const uno::Reference< embed::XStorage >& xStorage,
1371 const OUString& aTargetURL,
1372 const Reference< XSimpleFileAccess3 >& rToUseSFI,
1373 const Reference< XInteractionHandler >& xHandler )
1375 bool bLink = pLib->mbLink;
1376 bool bStorage = xStorage.is() && !bLink;
1378 Sequence< OUString > aElementNames = pLib->getElementNames();
1379 sal_Int32 nNameCount = aElementNames.getLength();
1380 const OUString* pNames = aElementNames.getConstArray();
1382 if( bStorage )
1384 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1386 OUString aElementName = pNames[ i ];
1387 OUString aStreamName = aElementName + ".xml";
1389 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
1391 SAL_WARN(
1392 "basic",
1393 "invalid library element \"" << aElementName << '"');
1394 continue;
1398 uno::Reference< io::XStream > xElementStream = xStorage->openStreamElement(
1399 aStreamName,
1400 embed::ElementModes::READWRITE );
1401 // throw uno::RuntimeException(); // TODO: method must either return the stream or throw an exception
1403 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
1404 SAL_WARN_IF(
1405 !xProps.is(), "basic",
1406 "The StorageStream must implement XPropertySet interface!");
1407 //if ( !xProps.is() ) //TODO
1409 if ( xProps.is() )
1411 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
1413 // #87671 Allow encryption
1414 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
1416 Reference< XOutputStream > xOutput = xElementStream->getOutputStream();
1417 Reference< XNameContainer > xLib( pLib );
1418 writeLibraryElement( xLib, aElementName, xOutput );
1421 catch(const uno::Exception& )
1423 SAL_WARN("basic", "Problem during storing of library!");
1424 // TODO: error handling?
1427 pLib->storeResourcesToStorage( xStorage );
1429 else
1431 // Export?
1432 bool bExport = !aTargetURL.isEmpty();
1435 Reference< XSimpleFileAccess3 > xSFI = mxSFI;
1436 if( rToUseSFI.is() )
1438 xSFI = rToUseSFI;
1440 OUString aLibDirPath;
1441 if( bExport )
1443 INetURLObject aInetObj( aTargetURL );
1444 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1445 aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1447 if( !xSFI->isFolder( aLibDirPath ) )
1449 xSFI->createFolder( aLibDirPath );
1451 pLib->storeResourcesToURL( aLibDirPath, xHandler );
1453 else
1455 aLibDirPath = createAppLibraryFolder( pLib, aName );
1456 pLib->storeResources();
1459 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1461 OUString aElementName = pNames[ i ];
1463 INetURLObject aElementInetObj( aLibDirPath );
1464 aElementInetObj.insertName( aElementName, false,
1465 INetURLObject::LAST_SEGMENT,
1466 INetURLObject::EncodeMechanism::All );
1467 aElementInetObj.setExtension( maLibElementFileExtension );
1468 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1470 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
1472 SAL_WARN(
1473 "basic",
1474 "invalid library element \"" << aElementName << '"');
1475 continue;
1478 // TODO: Check modified
1481 if( xSFI->exists( aElementPath ) )
1483 xSFI->kill( aElementPath );
1485 Reference< XOutputStream > xOutput = xSFI->openFileWrite( aElementPath );
1486 Reference< XNameContainer > xLib( pLib );
1487 writeLibraryElement( xLib, aElementName, xOutput );
1488 xOutput->closeOutput();
1490 catch(const Exception& )
1492 if( bExport )
1494 throw;
1496 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aElementPath );
1497 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1501 catch(const Exception& )
1503 if( bExport )
1505 throw;
1511 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib,
1512 const ::xmlscript::LibDescriptor& rLib,
1513 const uno::Reference< embed::XStorage >& xStorage )
1515 Reference< XSimpleFileAccess3 > xDummySFA;
1516 implStoreLibraryIndexFile( pLib, rLib, xStorage, OUString(), xDummySFA );
1519 // New variant for library export
1520 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib,
1521 const ::xmlscript::LibDescriptor& rLib,
1522 const uno::Reference< embed::XStorage >& xStorage,
1523 const OUString& aTargetURL,
1524 const Reference< XSimpleFileAccess3 >& rToUseSFI )
1526 // Create sax writer
1527 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
1529 bool bLink = pLib->mbLink;
1530 bool bStorage = xStorage.is() && !bLink;
1532 // Write info file
1533 uno::Reference< io::XOutputStream > xOut;
1534 uno::Reference< io::XStream > xInfoStream;
1535 if( bStorage )
1537 OUString aStreamName = maInfoFileName + "-lb.xml";
1541 xInfoStream = xStorage->openStreamElement( aStreamName, embed::ElementModes::READWRITE );
1542 SAL_WARN_IF(!xInfoStream.is(), "basic", "No stream!");
1543 uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY );
1544 // throw uno::RuntimeException(); // TODO
1546 if ( xProps.is() )
1548 xProps->setPropertyValue("MediaType", uno::Any( OUString("text/xml") ) );
1550 // #87671 Allow encryption
1551 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
1553 xOut = xInfoStream->getOutputStream();
1556 catch(const uno::Exception& )
1558 SAL_WARN("basic", "Problem during storing of library index file!");
1559 // TODO: error handling?
1562 else
1564 // Export?
1565 bool bExport = !aTargetURL.isEmpty();
1566 Reference< XSimpleFileAccess3 > xSFI = mxSFI;
1567 if( rToUseSFI.is() )
1569 xSFI = rToUseSFI;
1571 OUString aLibInfoPath;
1572 if( bExport )
1574 INetURLObject aInetObj( aTargetURL );
1575 aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1576 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1577 if( !xSFI->isFolder( aLibDirPath ) )
1579 xSFI->createFolder( aLibDirPath );
1581 aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1582 aInetObj.setExtension( "xlb" );
1583 aLibInfoPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1585 else
1587 createAppLibraryFolder( pLib, rLib.aName );
1588 aLibInfoPath = pLib->maLibInfoFileURL;
1593 if( xSFI->exists( aLibInfoPath ) )
1595 xSFI->kill( aLibInfoPath );
1597 xOut = xSFI->openFileWrite( aLibInfoPath );
1599 catch(const Exception& )
1601 if( bExport )
1603 throw;
1605 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath );
1606 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1609 if( !xOut.is() )
1611 SAL_WARN("basic", "couldn't open output stream");
1612 return;
1614 xWriter->setOutputStream( xOut );
1615 xmlscript::exportLibrary( xWriter, rLib );
1619 bool SfxLibraryContainer::implLoadLibraryIndexFile( SfxLibrary* pLib,
1620 ::xmlscript::LibDescriptor& rLib,
1621 const uno::Reference< embed::XStorage >& xStorage,
1622 const OUString& aIndexFileName )
1624 Reference< XParser > xParser = xml::sax::Parser::create(mxContext);
1626 bool bStorage = false;
1627 if( pLib )
1629 bool bLink = pLib->mbLink;
1630 bStorage = xStorage.is() && !bLink;
1633 // Read info file
1634 uno::Reference< io::XInputStream > xInput;
1635 OUString aLibInfoPath;
1636 if( bStorage )
1638 aLibInfoPath = maInfoFileName + "-lb.xml";
1642 uno::Reference< io::XStream > xInfoStream =
1643 xStorage->openStreamElement( aLibInfoPath, embed::ElementModes::READ );
1644 xInput = xInfoStream->getInputStream();
1646 catch(const uno::Exception& )
1649 else
1651 // Create Input stream
1652 //String aLibInfoPath; // attention: THIS PROBLEM MUST BE REVIEWED BY SCRIPTING OWNER!!!
1654 if( pLib )
1656 createAppLibraryFolder( pLib, rLib.aName );
1657 aLibInfoPath = pLib->maLibInfoFileURL;
1659 else
1661 aLibInfoPath = aIndexFileName;
1665 xInput = mxSFI->openFileRead( aLibInfoPath );
1667 catch(const Exception& )
1669 xInput.clear();
1670 if( !GbMigrationSuppressErrors )
1672 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath );
1673 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1677 if( !xInput.is() )
1679 return false;
1682 InputSource source;
1683 source.aInputStream = xInput;
1684 source.sSystemId = aLibInfoPath;
1686 // start parsing
1689 xParser->setDocumentHandler( ::xmlscript::importLibrary( rLib ) );
1690 xParser->parseStream( source );
1692 catch(const Exception& )
1694 SAL_WARN("basic", "Parsing error");
1695 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath );
1696 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1697 return false;
1700 if( !pLib )
1702 Reference< XNameContainer > xLib = createLibrary( rLib.aName );
1703 pLib = static_cast< SfxLibrary* >( xLib.get() );
1704 pLib->mbLoaded = false;
1705 rLib.aStorageURL = aIndexFileName;
1706 checkStorageURL( rLib.aStorageURL, pLib->maLibInfoFileURL, pLib->maStorageURL,
1707 pLib->maUnexpandedStorageURL );
1709 implImportLibDescriptor( pLib, rLib );
1712 return true;
1715 void SfxLibraryContainer::implImportLibDescriptor( SfxLibrary* pLib,
1716 ::xmlscript::LibDescriptor const & rLib )
1718 if( pLib->mbInitialised )
1719 return;
1721 sal_Int32 nElementCount = rLib.aElementNames.getLength();
1722 const OUString* pElementNames = rLib.aElementNames.getConstArray();
1723 Any aDummyElement = createEmptyLibraryElement();
1724 for( sal_Int32 i = 0 ; i < nElementCount ; i++ )
1726 pLib->maNameContainer->insertByName( pElementNames[i], aDummyElement );
1728 pLib->mbPasswordProtected = rLib.bPasswordProtected;
1729 pLib->mbReadOnly = rLib.bReadOnly;
1730 pLib->mbPreload = rLib.bPreload;
1731 pLib->implSetModified( false );
1732 pLib->mbInitialised = true;
1736 // Methods of new XLibraryStorage interface?
1737 void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference< embed::XStorage >& i_rStorage,
1738 bool bComplete )
1740 const Sequence< OUString > aNames = maNameContainer->getElementNames();
1741 const sal_Int32 nNameCount = aNames.getLength();
1742 const OUString* pName = aNames.getConstArray();
1743 const OUString* pNamesEnd = aNames.getConstArray() + nNameCount;
1745 // Don't count libs from shared index file
1746 sal_Int32 nLibsToSave = nNameCount;
1747 for( ; pName != pNamesEnd; ++pName )
1749 SfxLibrary* pImplLib = getImplLib( *pName );
1750 if( pImplLib->mbSharedIndexFile || pImplLib->mbExtension )
1752 nLibsToSave--;
1755 // Write to storage?
1756 bool bStorage = i_rStorage.is();
1757 uno::Reference< embed::XStorage > xSourceLibrariesStor;
1758 uno::Reference< embed::XStorage > xTargetLibrariesStor;
1759 OUString sTempTargetStorName;
1760 const bool bInplaceStorage = bStorage && ( i_rStorage == mxStorage );
1762 if( nLibsToSave == 0 )
1764 if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) )
1766 mxStorage->removeElement(maLibrariesDir);
1768 return;
1771 if ( bStorage )
1773 // Don't write if only empty standard lib exists
1774 if ( ( nLibsToSave == 1 ) && ( aNames[0] == "Standard" ) )
1776 Any aLibAny = maNameContainer->getByName( aNames[0] );
1777 Reference< XNameAccess > xNameAccess;
1778 aLibAny >>= xNameAccess;
1779 if ( ! xNameAccess->hasElements() )
1781 if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) )
1783 mxStorage->removeElement(maLibrariesDir);
1785 return;
1789 // create the empty target storage
1792 OUString sTargetLibrariesStoreName;
1793 if ( bInplaceStorage )
1795 // create a temporary target storage
1796 const OUStringBuffer aTempTargetNameBase = maLibrariesDir + "_temp_";
1797 sal_Int32 index = 0;
1800 OUStringBuffer aTempTargetName( aTempTargetNameBase );
1801 aTempTargetName.append( index++ );
1803 sTargetLibrariesStoreName = aTempTargetName.makeStringAndClear();
1804 if ( !i_rStorage->hasByName( sTargetLibrariesStoreName ) )
1806 break;
1809 while ( true );
1810 sTempTargetStorName = sTargetLibrariesStoreName;
1812 else
1814 sTargetLibrariesStoreName = maLibrariesDir;
1815 if ( i_rStorage->hasByName( sTargetLibrariesStoreName ) )
1817 i_rStorage->removeElement( sTargetLibrariesStoreName );
1821 xTargetLibrariesStor.set( i_rStorage->openStorageElement( sTargetLibrariesStoreName, embed::ElementModes::READWRITE ), UNO_SET_THROW );
1823 catch( const uno::Exception& )
1825 DBG_UNHANDLED_EXCEPTION("basic");
1826 return;
1829 // open the source storage which might be used to copy yet-unmodified libraries
1832 if ( mxStorage->hasByName( maLibrariesDir ) || bInplaceStorage )
1834 xSourceLibrariesStor = mxStorage->openStorageElement( maLibrariesDir,
1835 bInplaceStorage ? embed::ElementModes::READWRITE : embed::ElementModes::READ );
1838 catch( const uno::Exception& )
1840 DBG_UNHANDLED_EXCEPTION("basic");
1841 return;
1845 int iArray = 0;
1846 pName = aNames.getConstArray();
1847 ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs;
1848 auto pLibArray = std::make_unique< ::xmlscript::LibDescriptorArray > ( nLibsToSave );
1849 for( ; pName != pNamesEnd; ++pName )
1851 SfxLibrary* pImplLib = getImplLib( *pName );
1852 if( pImplLib->mbSharedIndexFile )
1854 continue;
1856 const bool bExtensionLib = pImplLib->mbExtension;
1857 ::xmlscript::LibDescriptor& rLib = bExtensionLib ?
1858 aLibDescriptorForExtensionLibs : pLibArray->mpLibs[iArray];
1859 if( !bExtensionLib )
1861 iArray++;
1863 rLib.aName = *pName;
1865 rLib.bLink = pImplLib->mbLink;
1866 if( !bStorage || pImplLib->mbLink )
1868 rLib.aStorageURL = ( pImplLib->maUnexpandedStorageURL.getLength() ) ?
1869 pImplLib->maUnexpandedStorageURL : pImplLib->maLibInfoFileURL;
1871 rLib.bReadOnly = pImplLib->mbReadOnly;
1872 rLib.bPreload = pImplLib->mbPreload;
1873 rLib.bPasswordProtected = pImplLib->mbPasswordProtected;
1874 rLib.aElementNames = pImplLib->getElementNames();
1876 if( pImplLib->implIsModified() || bComplete )
1878 // Testing pImplLib->implIsModified() is not reliable,
1879 // IMHO the value of pImplLib->implIsModified() should
1880 // reflect whether the library ( in-memory ) model
1881 // is in sync with the library container's own storage. Currently
1882 // whenever the library model is written to *any* storage
1883 // pImplLib->implSetModified( sal_False ) is called
1884 // The way the code works, especially the way that sfx uses
1885 // temp storage when saving ( and later sets the root storage of the
1886 // library container ) and similar madness in dbaccess means some surgery
1887 // is required to make it possible to successfully use this optimisation
1888 // It would be possible to do the implSetModified() call below only
1889 // conditionally, but that would require an additional boolean to be
1890 // passed in via the XStorageBasedDocument::storeLibrariesToStorage()...
1891 // fdo#68983: If there's a password and the password is not known, only
1892 // copying the storage works!
1893 // Can we simply copy the storage?
1894 bool isCopyStorage = !mbOldInfoFormat && !mbOasis2OOoFormat
1895 && !pImplLib->isLoadedStorable()
1896 && xSourceLibrariesStor.is() /* null for user profile */;
1897 if (isCopyStorage)
1901 (void)xSourceLibrariesStor->isStorageElement(rLib.aName);
1903 catch (container::NoSuchElementException const&)
1905 isCopyStorage = false;
1908 if (isCopyStorage)
1912 xSourceLibrariesStor->copyElementTo( rLib.aName, xTargetLibrariesStor, rLib.aName );
1914 catch( const uno::Exception& )
1916 DBG_UNHANDLED_EXCEPTION("basic");
1917 // TODO: error handling?
1920 else
1922 uno::Reference< embed::XStorage > xLibraryStor;
1923 if( bStorage )
1925 #if OSL_DEBUG_LEVEL > 0
1928 #endif
1929 xLibraryStor = xTargetLibrariesStor->openStorageElement(
1930 rLib.aName,
1931 embed::ElementModes::READWRITE );
1932 #if OSL_DEBUG_LEVEL > 0
1934 catch(const uno::Exception& )
1936 TOOLS_WARN_EXCEPTION(
1937 "basic",
1938 "couldn't create sub storage for library \"" << rLib.aName << "\"");
1939 throw;
1941 #endif
1944 // Maybe lib is not loaded?!
1945 if( bComplete )
1947 loadLibrary( rLib.aName );
1949 if( pImplLib->mbPasswordProtected )
1951 implStorePasswordLibrary( pImplLib, rLib.aName, xLibraryStor, uno::Reference< task::XInteractionHandler >() );
1952 // TODO: Check return value
1954 else
1956 implStoreLibrary( pImplLib, rLib.aName, xLibraryStor );
1958 implStoreLibraryIndexFile( pImplLib, rLib, xLibraryStor );
1959 if( bStorage )
1963 uno::Reference< embed::XTransactedObject > xTransact( xLibraryStor, uno::UNO_QUERY_THROW );
1964 xTransact->commit();
1966 catch(const uno::Exception& )
1968 DBG_UNHANDLED_EXCEPTION("basic");
1969 // TODO: error handling
1970 throw;
1974 maModifiable.setModified( true );
1975 pImplLib->implSetModified( false );
1978 // For container info ReadOnly refers to mbReadOnlyLink
1979 rLib.bReadOnly = pImplLib->mbReadOnlyLink;
1982 // if we did an in-place save into a storage (i.e. a save into the storage we were already based on),
1983 // then we need to clean up the temporary storage we used for this
1984 if ( bInplaceStorage && !sTempTargetStorName.isEmpty() )
1986 SAL_WARN_IF(
1987 !xSourceLibrariesStor.is(), "basic",
1988 ("SfxLibrariesContainer::storeLibraries_impl: unexpected: we should"
1989 " have a source storage here!"));
1992 // for this, we first remove everything from the source storage, then copy the complete content
1993 // from the temporary target storage. From then on, what used to be the "source storage" becomes
1994 // the "target storage" for all subsequent operations.
1996 // (We cannot simply remove the storage, denoted by maLibrariesDir, from i_rStorage - there might be
1997 // open references to it.)
1999 if ( xSourceLibrariesStor.is() )
2001 // remove
2002 const Sequence< OUString > aRemoveNames( xSourceLibrariesStor->getElementNames() );
2003 for ( auto const & removeName : aRemoveNames )
2005 xSourceLibrariesStor->removeElement( removeName );
2008 // copy
2009 const Sequence< OUString > aCopyNames( xTargetLibrariesStor->getElementNames() );
2010 for ( auto const & copyName : aCopyNames )
2012 xTargetLibrariesStor->copyElementTo( copyName, xSourceLibrariesStor, copyName );
2016 // close and remove temp target
2017 xTargetLibrariesStor->dispose();
2018 i_rStorage->removeElement( sTempTargetStorName );
2019 xTargetLibrariesStor.clear();
2020 sTempTargetStorName.clear();
2022 // adjust target
2023 xTargetLibrariesStor = xSourceLibrariesStor;
2024 xSourceLibrariesStor.clear();
2026 catch( const Exception& )
2028 DBG_UNHANDLED_EXCEPTION("basic");
2029 throw;
2033 if( !mbOldInfoFormat && !maModifiable.isModified() )
2035 return;
2037 maModifiable.setModified( false );
2038 mbOldInfoFormat = false;
2040 // Write library container info
2041 // Create sax writer
2042 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
2044 // Write info file
2045 uno::Reference< io::XOutputStream > xOut;
2046 uno::Reference< io::XStream > xInfoStream;
2047 if( bStorage )
2049 OUString aStreamName = maInfoFileName + "-lc.xml";
2053 xInfoStream = xTargetLibrariesStor->openStreamElement( aStreamName, embed::ElementModes::READWRITE );
2054 uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY_THROW );
2055 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
2057 // #87671 Allow encryption
2058 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
2060 xOut = xInfoStream->getOutputStream();
2062 catch(const uno::Exception& )
2064 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
2067 else
2069 // Create Output stream
2070 INetURLObject aLibInfoInetObj( maLibraryPath.getToken(1, ';') );
2071 aLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
2072 aLibInfoInetObj.setExtension( "xlc" );
2073 OUString aLibInfoPath( aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2077 if( mxSFI->exists( aLibInfoPath ) )
2079 mxSFI->kill( aLibInfoPath );
2081 xOut = mxSFI->openFileWrite( aLibInfoPath );
2083 catch(const Exception& )
2085 xOut.clear();
2086 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath );
2087 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
2091 if( !xOut.is() )
2093 SAL_WARN("basic", "couldn't open output stream");
2094 return;
2097 xWriter->setOutputStream( xOut );
2101 xmlscript::exportLibraryContainer( xWriter, pLibArray.get() );
2102 if ( bStorage )
2104 uno::Reference< embed::XTransactedObject > xTransact( xTargetLibrariesStor, uno::UNO_QUERY_THROW );
2105 xTransact->commit();
2108 catch(const uno::Exception& )
2110 SAL_WARN("basic", "Problem during storing of libraries!");
2111 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
2116 // Methods XElementAccess
2117 Type SAL_CALL SfxLibraryContainer::getElementType()
2119 LibraryContainerMethodGuard aGuard( *this );
2120 return maNameContainer->getElementType();
2123 sal_Bool SfxLibraryContainer::hasElements()
2125 LibraryContainerMethodGuard aGuard( *this );
2126 bool bRet = maNameContainer->hasElements();
2127 return bRet;
2130 // Methods XNameAccess
2131 Any SfxLibraryContainer::getByName( const OUString& aName )
2133 LibraryContainerMethodGuard aGuard( *this );
2134 Any aRetAny = maNameContainer->getByName( aName ) ;
2135 return aRetAny;
2138 Sequence< OUString > SfxLibraryContainer::getElementNames()
2140 LibraryContainerMethodGuard aGuard( *this );
2141 return maNameContainer->getElementNames();
2144 sal_Bool SfxLibraryContainer::hasByName( const OUString& aName )
2146 LibraryContainerMethodGuard aGuard( *this );
2147 return maNameContainer->hasByName( aName ) ;
2150 // Methods XLibraryContainer
2151 Reference< XNameContainer > SAL_CALL SfxLibraryContainer::createLibrary( const OUString& Name )
2153 LibraryContainerMethodGuard aGuard( *this );
2154 SfxLibrary* pNewLib = implCreateLibrary( Name );
2155 pNewLib->maLibElementFileExtension = maLibElementFileExtension;
2157 createVariableURL( pNewLib->maUnexpandedStorageURL, Name, maInfoFileName, true );
2159 Reference< XNameAccess > xNameAccess = static_cast< XNameAccess* >( pNewLib );
2160 Any aElement;
2161 aElement <<= xNameAccess;
2162 maNameContainer->insertByName( Name, aElement );
2163 maModifiable.setModified( true );
2164 Reference< XNameContainer > xRet( xNameAccess, UNO_QUERY );
2165 return xRet;
2168 Reference< XNameAccess > SAL_CALL SfxLibraryContainer::createLibraryLink
2169 ( const OUString& Name, const OUString& StorageURL, sal_Bool ReadOnly )
2171 LibraryContainerMethodGuard aGuard( *this );
2172 // TODO: Check other reasons to force ReadOnly status
2173 //if( !ReadOnly )
2177 OUString aLibInfoFileURL;
2178 OUString aLibDirURL;
2179 OUString aUnexpandedStorageURL;
2180 checkStorageURL( StorageURL, aLibInfoFileURL, aLibDirURL, aUnexpandedStorageURL );
2183 SfxLibrary* pNewLib = implCreateLibraryLink( Name, aLibInfoFileURL, aLibDirURL, ReadOnly );
2184 pNewLib->maLibElementFileExtension = maLibElementFileExtension;
2185 pNewLib->maUnexpandedStorageURL = aUnexpandedStorageURL;
2186 pNewLib->maOriginalStorageURL = StorageURL;
2188 uno::Reference< embed::XStorage > xDummyStor;
2189 ::xmlscript::LibDescriptor aLibDesc;
2190 implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, OUString() );
2191 implImportLibDescriptor( pNewLib, aLibDesc );
2193 Reference< XNameAccess > xRet = static_cast< XNameAccess* >( pNewLib );
2194 Any aElement;
2195 aElement <<= xRet;
2196 maNameContainer->insertByName( Name, aElement );
2197 maModifiable.setModified( true );
2199 if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 )
2201 pNewLib->mbExtension = true;
2203 else if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1
2204 || StorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 )
2206 pNewLib->mbExtension = true;
2207 pNewLib->mbReadOnly = true;
2210 return xRet;
2213 void SAL_CALL SfxLibraryContainer::removeLibrary( const OUString& Name )
2215 LibraryContainerMethodGuard aGuard( *this );
2216 // Get and hold library before removing
2217 Any aLibAny = maNameContainer->getByName( Name ) ;
2218 Reference< XNameAccess > xNameAccess;
2219 aLibAny >>= xNameAccess;
2220 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
2221 if( pImplLib->mbReadOnly && !pImplLib->mbLink )
2223 throw IllegalArgumentException();
2225 // Remove from container
2226 maNameContainer->removeByName( Name );
2227 maModifiable.setModified( true );
2229 // Delete library files, but not for linked libraries
2230 if( pImplLib->mbLink )
2231 return;
2233 if( mxStorage.is() )
2235 return;
2237 if( xNameAccess->hasElements() )
2239 Sequence< OUString > aNames = pImplLib->getElementNames();
2240 sal_Int32 nNameCount = aNames.getLength();
2241 const OUString* pNames = aNames.getConstArray();
2242 for( sal_Int32 i = 0 ; i < nNameCount ; ++i, ++pNames )
2244 pImplLib->removeElementWithoutChecks( *pNames, SfxLibrary::LibraryContainerAccess() );
2248 // Delete index file
2249 createAppLibraryFolder( pImplLib, Name );
2250 OUString aLibInfoPath = pImplLib->maLibInfoFileURL;
2253 if( mxSFI->exists( aLibInfoPath ) )
2255 mxSFI->kill( aLibInfoPath );
2258 catch(const Exception& ) {}
2260 // Delete folder if empty
2261 INetURLObject aInetObj( maLibraryPath.getToken(1, ';') );
2262 aInetObj.insertName( Name, true, INetURLObject::LAST_SEGMENT,
2263 INetURLObject::EncodeMechanism::All );
2264 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2268 if( mxSFI->isFolder( aLibDirPath ) )
2270 Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true );
2271 sal_Int32 nCount = aContentSeq.getLength();
2272 if( !nCount )
2274 mxSFI->kill( aLibDirPath );
2278 catch(const Exception& )
2283 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLoaded( const OUString& Name )
2285 LibraryContainerMethodGuard aGuard( *this );
2286 SfxLibrary* pImplLib = getImplLib( Name );
2287 bool bRet = pImplLib->mbLoaded;
2288 return bRet;
2292 void SAL_CALL SfxLibraryContainer::loadLibrary( const OUString& Name )
2294 LibraryContainerMethodGuard aGuard( *this );
2295 Any aLibAny = maNameContainer->getByName( Name ) ;
2296 Reference< XNameAccess > xNameAccess;
2297 aLibAny >>= xNameAccess;
2298 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
2300 bool bLoaded = pImplLib->mbLoaded;
2301 pImplLib->mbLoaded = true;
2302 if( bLoaded || !xNameAccess->hasElements() )
2303 return;
2305 if( pImplLib->mbPasswordProtected )
2307 implLoadPasswordLibrary( pImplLib, Name );
2308 return;
2311 bool bLink = pImplLib->mbLink;
2312 bool bStorage = mxStorage.is() && !bLink;
2314 uno::Reference< embed::XStorage > xLibrariesStor;
2315 uno::Reference< embed::XStorage > xLibraryStor;
2316 if( bStorage )
2318 #if OSL_DEBUG_LEVEL > 0
2321 #endif
2322 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
2323 SAL_WARN_IF(
2324 !xLibrariesStor.is(), "basic",
2325 ("The method must either throw exception or return a"
2326 " storage!"));
2327 if ( !xLibrariesStor.is() )
2329 throw uno::RuntimeException("null returned from openStorageElement");
2332 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
2333 SAL_WARN_IF(
2334 !xLibraryStor.is(), "basic",
2335 ("The method must either throw exception or return a"
2336 " storage!"));
2337 if ( !xLibrariesStor.is() )
2339 throw uno::RuntimeException("null returned from openStorageElement");
2341 #if OSL_DEBUG_LEVEL > 0
2343 catch(const uno::Exception& )
2345 TOOLS_WARN_EXCEPTION(
2346 "basic",
2347 "couldn't open sub storage for library \"" << Name << "\"");
2348 throw;
2350 #endif
2353 Sequence< OUString > aNames = pImplLib->getElementNames();
2354 sal_Int32 nNameCount = aNames.getLength();
2355 const OUString* pNames = aNames.getConstArray();
2356 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
2358 OUString aElementName = pNames[ i ];
2360 OUString aFile;
2361 uno::Reference< io::XInputStream > xInStream;
2363 if( bStorage )
2365 uno::Reference< io::XStream > xElementStream;
2367 aFile = aElementName + ".xml";
2371 xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ );
2373 catch(const uno::Exception& )
2376 if( !xElementStream.is() )
2378 // Check for EA2 document version with wrong extensions
2379 aFile = aElementName + "." + maLibElementFileExtension;
2382 xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ );
2384 catch(const uno::Exception& )
2388 if ( xElementStream.is() )
2390 xInStream = xElementStream->getInputStream();
2392 if ( !xInStream.is() )
2394 SAL_WARN(
2395 "basic",
2396 "couldn't open library element stream - attempted to"
2397 " open library \"" << Name << '"');
2398 throw RuntimeException("couldn't open library element stream", *this);
2401 else
2403 OUString aLibDirPath = pImplLib->maStorageURL;
2404 INetURLObject aElementInetObj( aLibDirPath );
2405 aElementInetObj.insertName( aElementName, false,
2406 INetURLObject::LAST_SEGMENT,
2407 INetURLObject::EncodeMechanism::All );
2408 aElementInetObj.setExtension( maLibElementFileExtension );
2409 aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2412 Reference< XNameContainer > xLib( pImplLib );
2413 Any aAny = importLibraryElement( xLib, aElementName,
2414 aFile, xInStream );
2415 if( pImplLib->hasByName( aElementName ) )
2417 if( aAny.hasValue() )
2419 pImplLib->maNameContainer->replaceByName( aElementName, aAny );
2422 else
2424 pImplLib->maNameContainer->insertNoCheck(aElementName, aAny);
2427 pImplLib->implSetModified( false );
2430 // Methods XLibraryContainer2
2431 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLink( const OUString& Name )
2433 LibraryContainerMethodGuard aGuard( *this );
2434 SfxLibrary* pImplLib = getImplLib( Name );
2435 bool bRet = pImplLib->mbLink;
2436 return bRet;
2439 OUString SAL_CALL SfxLibraryContainer::getLibraryLinkURL( const OUString& Name )
2441 LibraryContainerMethodGuard aGuard( *this );
2442 SfxLibrary* pImplLib = getImplLib( Name );
2443 bool bLink = pImplLib->mbLink;
2444 if( !bLink )
2446 throw IllegalArgumentException();
2448 OUString aRetStr = pImplLib->maLibInfoFileURL;
2449 return aRetStr;
2452 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryReadOnly( const OUString& Name )
2454 LibraryContainerMethodGuard aGuard( *this );
2455 SfxLibrary* pImplLib = getImplLib( Name );
2456 bool bRet = pImplLib->mbReadOnly || (pImplLib->mbLink && pImplLib->mbReadOnlyLink);
2457 return bRet;
2460 void SAL_CALL SfxLibraryContainer::setLibraryReadOnly( const OUString& Name, sal_Bool bReadOnly )
2462 LibraryContainerMethodGuard aGuard( *this );
2463 SfxLibrary* pImplLib = getImplLib( Name );
2464 if( pImplLib->mbLink )
2466 if( pImplLib->mbReadOnlyLink != bool(bReadOnly) )
2468 pImplLib->mbReadOnlyLink = bReadOnly;
2469 pImplLib->implSetModified( true );
2470 maModifiable.setModified( true );
2473 else
2475 if( pImplLib->mbReadOnly != bool(bReadOnly) )
2477 pImplLib->mbReadOnly = bReadOnly;
2478 pImplLib->implSetModified( true );
2483 void SAL_CALL SfxLibraryContainer::renameLibrary( const OUString& Name, const OUString& NewName )
2485 LibraryContainerMethodGuard aGuard( *this );
2486 if( maNameContainer->hasByName( NewName ) )
2488 throw ElementExistException();
2490 // Get and hold library before removing
2491 Any aLibAny = maNameContainer->getByName( Name ) ;
2493 // #i24094 Maybe lib is not loaded!
2494 Reference< XNameAccess > xNameAccess;
2495 aLibAny >>= xNameAccess;
2496 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
2497 if( pImplLib->mbPasswordProtected && !pImplLib->mbPasswordVerified )
2499 return; // Lib with unverified password cannot be renamed
2501 loadLibrary( Name );
2503 // Remove from container
2504 maNameContainer->removeByName( Name );
2505 maModifiable.setModified( true );
2507 // Rename library folder, but not for linked libraries
2508 bool bMovedSuccessful = true;
2510 // Rename files
2511 bool bStorage = mxStorage.is();
2512 if( !bStorage && !pImplLib->mbLink )
2514 bMovedSuccessful = false;
2516 OUString aLibDirPath = pImplLib->maStorageURL;
2518 INetURLObject aDestInetObj( maLibraryPath.getToken(1, ';'));
2519 aDestInetObj.insertName( NewName, true, INetURLObject::LAST_SEGMENT,
2520 INetURLObject::EncodeMechanism::All );
2521 OUString aDestDirPath = aDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2523 // Store new URL
2524 OUString aLibInfoFileURL = pImplLib->maLibInfoFileURL;
2525 checkStorageURL( aDestDirPath, pImplLib->maLibInfoFileURL, pImplLib->maStorageURL,
2526 pImplLib->maUnexpandedStorageURL );
2530 if( mxSFI->isFolder( aLibDirPath ) )
2532 if( !mxSFI->isFolder( aDestDirPath ) )
2534 mxSFI->createFolder( aDestDirPath );
2536 // Move index file
2539 if( mxSFI->exists( pImplLib->maLibInfoFileURL ) )
2541 mxSFI->kill( pImplLib->maLibInfoFileURL );
2543 mxSFI->move( aLibInfoFileURL, pImplLib->maLibInfoFileURL );
2545 catch(const Exception& )
2549 Sequence< OUString > aElementNames = xNameAccess->getElementNames();
2550 sal_Int32 nNameCount = aElementNames.getLength();
2551 const OUString* pNames = aElementNames.getConstArray();
2552 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
2554 OUString aElementName = pNames[ i ];
2556 INetURLObject aElementInetObj( aLibDirPath );
2557 aElementInetObj.insertName( aElementName, false,
2558 INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
2559 aElementInetObj.setExtension( maLibElementFileExtension );
2560 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2562 INetURLObject aElementDestInetObj( aDestDirPath );
2563 aElementDestInetObj.insertName( aElementName, false,
2564 INetURLObject::LAST_SEGMENT,
2565 INetURLObject::EncodeMechanism::All );
2566 aElementDestInetObj.setExtension( maLibElementFileExtension );
2567 OUString aDestElementPath( aElementDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2571 if( mxSFI->exists( aDestElementPath ) )
2573 mxSFI->kill( aDestElementPath );
2575 mxSFI->move( aElementPath, aDestElementPath );
2577 catch(const Exception& )
2581 pImplLib->storeResourcesAsURL( aDestDirPath, NewName );
2583 // Delete folder if empty
2584 Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true );
2585 sal_Int32 nCount = aContentSeq.getLength();
2586 if( !nCount )
2588 mxSFI->kill( aLibDirPath );
2591 bMovedSuccessful = true;
2592 pImplLib->implSetModified( true );
2595 catch(const Exception& )
2597 // Restore old library
2598 maNameContainer->insertByName( Name, aLibAny ) ;
2602 if( bStorage && !pImplLib->mbLink )
2604 pImplLib->implSetModified( true );
2606 if( bMovedSuccessful )
2608 maNameContainer->insertByName( NewName, aLibAny ) ;
2613 // Methods XInitialization
2614 void SAL_CALL SfxLibraryContainer::initialize( const Sequence< Any >& _rArguments )
2616 LibraryContainerMethodGuard aGuard( *this );
2617 sal_Int32 nArgCount = _rArguments.getLength();
2618 if ( nArgCount == 1 )
2620 OUString sInitialDocumentURL;
2621 Reference< XStorageBasedDocument > xDocument;
2622 if ( _rArguments[0] >>= sInitialDocumentURL )
2624 init( sInitialDocumentURL, nullptr );
2625 return;
2628 if ( _rArguments[0] >>= xDocument )
2630 initializeFromDocument( xDocument );
2631 return;
2635 throw IllegalArgumentException();
2638 void SfxLibraryContainer::initializeFromDocument( const Reference< XStorageBasedDocument >& _rxDocument )
2640 // check whether this is a valid OfficeDocument, and obtain the document's root storage
2641 Reference< XStorage > xDocStorage;
2644 Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY_THROW );
2645 if ( xSI->supportsService("com.sun.star.document.OfficeDocument"))
2647 xDocStorage.set( _rxDocument->getDocumentStorage(), UNO_SET_THROW );
2649 Reference< XModel > xDocument( _rxDocument, UNO_QUERY_THROW );
2650 Reference< XComponent > xDocComponent( _rxDocument, UNO_QUERY_THROW );
2652 mxOwnerDocument = xDocument;
2653 startComponentListening( xDocComponent );
2655 catch( const Exception& ) { }
2657 if ( !xDocStorage.is() )
2659 throw IllegalArgumentException();
2661 init( OUString(), xDocStorage );
2664 // OEventListenerAdapter
2665 void SfxLibraryContainer::_disposing( const EventObject& _rSource )
2667 #if OSL_DEBUG_LEVEL > 0
2668 Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY );
2669 SAL_WARN_IF(
2670 xDocument != _rSource.Source || !xDocument.is(), "basic",
2671 "SfxLibraryContainer::_disposing: where does this come from?");
2672 #else
2673 (void)_rSource;
2674 #endif
2675 dispose();
2678 // OComponentHelper
2679 void SAL_CALL SfxLibraryContainer::disposing()
2681 Reference< XModel > xModel = mxOwnerDocument;
2682 EventObject aEvent( xModel.get() );
2683 maVBAScriptListeners.disposing( aEvent );
2684 stopAllComponentListening();
2685 mxOwnerDocument.clear();
2688 // Methods XLibraryContainerPassword
2689 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordProtected( const OUString& )
2691 return false;
2694 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordVerified( const OUString& )
2696 throw IllegalArgumentException();
2699 sal_Bool SAL_CALL SfxLibraryContainer::verifyLibraryPassword( const OUString&, const OUString& )
2701 throw IllegalArgumentException();
2704 void SAL_CALL SfxLibraryContainer::changeLibraryPassword(const OUString&, const OUString&, const OUString& )
2706 throw IllegalArgumentException();
2709 // Methods XContainer
2710 void SAL_CALL SfxLibraryContainer::addContainerListener( const Reference< XContainerListener >& xListener )
2712 LibraryContainerMethodGuard aGuard( *this );
2713 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
2714 maNameContainer->addContainerListener( xListener );
2717 void SAL_CALL SfxLibraryContainer::removeContainerListener( const Reference< XContainerListener >& xListener )
2719 LibraryContainerMethodGuard aGuard( *this );
2720 maNameContainer->removeContainerListener( xListener );
2723 // Methods XLibraryContainerExport
2724 void SAL_CALL SfxLibraryContainer::exportLibrary( const OUString& Name, const OUString& URL,
2725 const Reference< XInteractionHandler >& Handler )
2727 LibraryContainerMethodGuard aGuard( *this );
2728 SfxLibrary* pImplLib = getImplLib( Name );
2730 Reference< XSimpleFileAccess3 > xToUseSFI;
2731 if( Handler.is() )
2733 xToUseSFI = ucb::SimpleFileAccess::create( mxContext );
2734 xToUseSFI->setInteractionHandler( Handler );
2737 // Maybe lib is not loaded?!
2738 loadLibrary( Name );
2740 uno::Reference< css::embed::XStorage > xDummyStor;
2741 if( pImplLib->mbPasswordProtected )
2743 implStorePasswordLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler );
2745 else
2747 implStoreLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler );
2749 ::xmlscript::LibDescriptor aLibDesc;
2750 aLibDesc.aName = Name;
2751 aLibDesc.bLink = false; // Link status gets lost?
2752 aLibDesc.bReadOnly = pImplLib->mbReadOnly;
2753 aLibDesc.bPreload = false; // Preload status gets lost?
2754 aLibDesc.bPasswordProtected = pImplLib->mbPasswordProtected;
2755 aLibDesc.aElementNames = pImplLib->getElementNames();
2757 implStoreLibraryIndexFile( pImplLib, aLibDesc, xDummyStor, URL, xToUseSFI );
2760 OUString SfxLibraryContainer::expand_url( const OUString& url )
2762 if (url.startsWithIgnoreAsciiCase( "vnd.sun.star.expand:" ))
2764 return comphelper::getExpandedUri(mxContext, url);
2766 else if( mxStringSubstitution.is() )
2768 OUString ret( mxStringSubstitution->substituteVariables( url, false ) );
2769 return ret;
2771 else
2773 return url;
2777 //XLibraryContainer3
2778 OUString SAL_CALL SfxLibraryContainer::getOriginalLibraryLinkURL( const OUString& Name )
2780 LibraryContainerMethodGuard aGuard( *this );
2781 SfxLibrary* pImplLib = getImplLib( Name );
2782 bool bLink = pImplLib->mbLink;
2783 if( !bLink )
2785 throw IllegalArgumentException();
2787 OUString aRetStr = pImplLib->maOriginalStorageURL;
2788 return aRetStr;
2792 // XVBACompatibility
2793 sal_Bool SAL_CALL SfxLibraryContainer::getVBACompatibilityMode()
2795 return mbVBACompat;
2798 void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( sal_Bool _vbacompatmodeon )
2800 /* The member variable mbVBACompat must be set first, the following call
2801 to getBasicManager() may call getVBACompatibilityMode() which returns
2802 this value. */
2803 mbVBACompat = _vbacompatmodeon;
2804 BasicManager* pBasMgr = getBasicManager();
2805 if( !pBasMgr )
2806 return;
2808 // get the standard library
2809 OUString aLibName = pBasMgr->GetName();
2810 if ( aLibName.isEmpty())
2812 aLibName = "Standard";
2814 if( StarBASIC* pBasic = pBasMgr->GetLib( aLibName ) )
2816 pBasic->SetVBAEnabled( _vbacompatmodeon );
2818 /* If in VBA compatibility mode, force creation of the VBA Globals
2819 object. Each application will create an instance of its own
2820 implementation and store it in its Basic manager. Implementations
2821 will do all necessary additional initialization, such as
2822 registering the global "This***Doc" UNO constant, starting the
2823 document events processor etc.
2825 if( mbVBACompat ) try
2827 Reference< XModel > xModel( mxOwnerDocument ); // weak-ref -> ref
2828 Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
2829 xFactory->createInstance("ooo.vba.VBAGlobals");
2831 catch(const Exception& )
2836 void SAL_CALL SfxLibraryContainer::setProjectName( const OUString& _projectname )
2838 msProjectName = _projectname;
2839 BasicManager* pBasMgr = getBasicManager();
2840 // Temporary HACK
2841 // Some parts of the VBA handling ( e.g. in core basic )
2842 // code expect the name of the VBA project to be set as the name of
2843 // the basic manager. Provide fail back here.
2844 if( pBasMgr )
2846 pBasMgr->SetName( msProjectName );
2850 sal_Int32 SAL_CALL SfxLibraryContainer::getRunningVBAScripts()
2852 LibraryContainerMethodGuard aGuard( *this );
2853 return mnRunningVBAScripts;
2856 void SAL_CALL SfxLibraryContainer::addVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener )
2858 maVBAScriptListeners.addTypedListener( rxListener );
2861 void SAL_CALL SfxLibraryContainer::removeVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener )
2863 maVBAScriptListeners.removeTypedListener( rxListener );
2866 void SAL_CALL SfxLibraryContainer::broadcastVBAScriptEvent( sal_Int32 nIdentifier, const OUString& rModuleName )
2868 // own lock for accessing the number of running scripts
2869 enterMethod();
2870 switch( nIdentifier )
2872 case vba::VBAScriptEventId::SCRIPT_STARTED:
2873 ++mnRunningVBAScripts;
2874 break;
2875 case vba::VBAScriptEventId::SCRIPT_STOPPED:
2876 --mnRunningVBAScripts;
2877 break;
2879 leaveMethod();
2881 Reference< XModel > xModel = mxOwnerDocument; // weak-ref -> ref
2882 vba::VBAScriptEvent aEvent( Reference<XInterface>(xModel, UNO_QUERY), nIdentifier, rModuleName );
2883 maVBAScriptListeners.notify( aEvent );
2886 // Methods XServiceInfo
2887 sal_Bool SAL_CALL SfxLibraryContainer::supportsService( const OUString& _rServiceName )
2889 return cppu::supportsService(this, _rServiceName);
2892 // Implementation class SfxLibrary
2894 // Ctor
2895 SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType,
2896 const Reference< XSimpleFileAccess3 >& xSFI )
2897 : OComponentHelper( m_aMutex )
2898 , mxSFI( xSFI )
2899 , mrModifiable( _rModifiable )
2900 , maNameContainer( new NameContainer(aType) )
2901 , mbLoaded( true )
2902 , mbIsModified( true )
2903 , mbInitialised( false )
2904 , mbLink( false )
2905 , mbReadOnly( false )
2906 , mbReadOnlyLink( false )
2907 , mbPreload( false )
2908 , mbPasswordProtected( false )
2909 , mbPasswordVerified( false )
2910 , mbDoc50Password( false )
2911 , mbSharedIndexFile( false )
2912 , mbExtension( false )
2916 SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType,
2917 const Reference< XSimpleFileAccess3 >& xSFI,
2918 const OUString& aLibInfoFileURL, const OUString& aStorageURL, bool ReadOnly )
2919 : OComponentHelper( m_aMutex )
2920 , mxSFI( xSFI )
2921 , mrModifiable( _rModifiable )
2922 , maNameContainer( new NameContainer(aType) )
2923 , mbLoaded( false )
2924 , mbIsModified( true )
2925 , mbInitialised( false )
2926 , maLibInfoFileURL( aLibInfoFileURL )
2927 , maStorageURL( aStorageURL )
2928 , mbLink( true )
2929 , mbReadOnly( false )
2930 , mbReadOnlyLink( ReadOnly )
2931 , mbPreload( false )
2932 , mbPasswordProtected( false )
2933 , mbPasswordVerified( false )
2934 , mbDoc50Password( false )
2935 , mbSharedIndexFile( false )
2936 , mbExtension( false )
2940 bool SfxLibrary::isLoadedStorable()
2942 return mbLoaded && (!mbPasswordProtected || mbPasswordVerified);
2945 void SfxLibrary::implSetModified( bool _bIsModified )
2947 if ( mbIsModified == _bIsModified )
2949 return;
2951 mbIsModified = _bIsModified;
2952 if ( mbIsModified )
2954 mrModifiable.setModified( true );
2958 // Methods XInterface
2959 Any SAL_CALL SfxLibrary::queryInterface( const Type& rType )
2961 Any aRet =
2962 ::cppu::queryInterface(
2963 rType,
2964 static_cast< XContainer * >( this ),
2965 static_cast< XNameContainer * >( this ),
2966 static_cast< XNameAccess * >( this ),
2967 static_cast< XElementAccess * >( this ),
2968 static_cast< XChangesNotifier * >( this ) );
2969 if( !aRet.hasValue() )
2971 aRet = OComponentHelper::queryInterface( rType );
2973 return aRet;
2976 // Methods XElementAccess
2977 Type SfxLibrary::getElementType()
2979 return maNameContainer->getElementType();
2982 sal_Bool SfxLibrary::hasElements()
2984 bool bRet = maNameContainer->hasElements();
2985 return bRet;
2988 // Methods XNameAccess
2989 Any SfxLibrary::getByName( const OUString& aName )
2991 impl_checkLoaded();
2993 Any aRetAny = maNameContainer->getByName( aName ) ;
2994 return aRetAny;
2997 Sequence< OUString > SfxLibrary::getElementNames()
2999 return maNameContainer->getElementNames();
3002 sal_Bool SfxLibrary::hasByName( const OUString& aName )
3004 bool bRet = maNameContainer->hasByName( aName );
3005 return bRet;
3008 void SfxLibrary::impl_checkReadOnly()
3010 if( mbReadOnly || (mbLink && mbReadOnlyLink) )
3012 throw IllegalArgumentException(
3013 "Library is readonly.",
3014 // TODO: resource
3015 *this, 0
3020 void SfxLibrary::impl_checkLoaded()
3022 if ( !mbLoaded )
3024 throw WrappedTargetException(
3025 OUString(),
3026 *this,
3027 Any( LibraryNotLoadedException(
3028 OUString(),
3029 *this
3035 // Methods XNameReplace
3036 void SfxLibrary::replaceByName( const OUString& aName, const Any& aElement )
3038 impl_checkReadOnly();
3039 impl_checkLoaded();
3041 SAL_WARN_IF(
3042 !isLibraryElementValid(aElement), "basic",
3043 "SfxLibrary::replaceByName: replacing element is invalid!");
3045 maNameContainer->replaceByName( aName, aElement );
3046 implSetModified( true );
3050 // Methods XNameContainer
3051 void SfxLibrary::insertByName( const OUString& aName, const Any& aElement )
3053 impl_checkReadOnly();
3054 impl_checkLoaded();
3056 SAL_WARN_IF(
3057 !isLibraryElementValid(aElement), "basic",
3058 "SfxLibrary::insertByName: to-be-inserted element is invalid!");
3060 maNameContainer->insertByName( aName, aElement );
3061 implSetModified( true );
3064 void SfxLibrary::impl_removeWithoutChecks( const OUString& _rElementName )
3066 maNameContainer->removeByName( _rElementName );
3067 implSetModified( true );
3069 // Remove element file
3070 if( maStorageURL.isEmpty() )
3071 return;
3073 INetURLObject aElementInetObj( maStorageURL );
3074 aElementInetObj.insertName( _rElementName, false,
3075 INetURLObject::LAST_SEGMENT,
3076 INetURLObject::EncodeMechanism::All );
3077 aElementInetObj.setExtension( maLibElementFileExtension );
3078 OUString aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
3082 if( mxSFI->exists( aFile ) )
3084 mxSFI->kill( aFile );
3087 catch(const Exception& )
3089 DBG_UNHANDLED_EXCEPTION("basic");
3093 void SfxLibrary::removeByName( const OUString& Name )
3095 impl_checkReadOnly();
3096 impl_checkLoaded();
3097 impl_removeWithoutChecks( Name );
3100 // XTypeProvider
3101 Sequence< Type > SfxLibrary::getTypes()
3103 static OTypeCollection ourTypes_NameContainer(
3104 cppu::UnoType<XNameContainer>::get(),
3105 cppu::UnoType<XContainer>::get(),
3106 cppu::UnoType<XChangesNotifier>::get(),
3107 OComponentHelper::getTypes() );
3109 return ourTypes_NameContainer.getTypes();
3113 Sequence< sal_Int8 > SfxLibrary::getImplementationId()
3115 return css::uno::Sequence<sal_Int8>();
3118 // Methods XContainer
3119 void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener )
3121 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
3122 maNameContainer->addContainerListener( xListener );
3125 void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerListener >& xListener )
3127 maNameContainer->removeContainerListener( xListener );
3130 // Methods XChangesNotifier
3131 void SAL_CALL SfxLibrary::addChangesListener( const Reference< XChangesListener >& xListener )
3133 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
3134 maNameContainer->addChangesListener( xListener );
3137 void SAL_CALL SfxLibrary::removeChangesListener( const Reference< XChangesListener >& xListener )
3139 maNameContainer->removeChangesListener( xListener );
3143 // Implementation class ScriptExtensionIterator
3145 #define sBasicLibMediaType "application/vnd.sun.star.basic-library"
3146 #define sDialogLibMediaType "application/vnd.sun.star.dialog-library"
3148 ScriptExtensionIterator::ScriptExtensionIterator()
3149 : m_xContext( comphelper::getProcessComponentContext() )
3150 , m_eState( USER_EXTENSIONS )
3151 , m_bUserPackagesLoaded( false )
3152 , m_bSharedPackagesLoaded( false )
3153 , m_bBundledPackagesLoaded( false )
3154 , m_iUserPackage( 0 )
3155 , m_iSharedPackage( 0 )
3156 , m_iBundledPackage( 0 )
3157 , m_pScriptSubPackageIterator( nullptr )
3160 OUString ScriptExtensionIterator::nextBasicOrDialogLibrary( bool& rbPureDialogLib )
3162 OUString aRetLib;
3164 while( aRetLib.isEmpty() && m_eState != END_REACHED )
3166 switch( m_eState )
3168 case USER_EXTENSIONS:
3170 Reference< deployment::XPackage > xScriptPackage =
3171 implGetNextUserScriptPackage( rbPureDialogLib );
3172 if( !xScriptPackage.is() )
3174 break;
3176 aRetLib = xScriptPackage->getURL();
3177 break;
3180 case SHARED_EXTENSIONS:
3182 Reference< deployment::XPackage > xScriptPackage =
3183 implGetNextSharedScriptPackage( rbPureDialogLib );
3184 if( !xScriptPackage.is() )
3186 break;
3188 aRetLib = xScriptPackage->getURL();
3189 break;
3191 case BUNDLED_EXTENSIONS:
3193 Reference< deployment::XPackage > xScriptPackage =
3194 implGetNextBundledScriptPackage( rbPureDialogLib );
3195 if( !xScriptPackage.is() )
3197 break;
3199 aRetLib = xScriptPackage->getURL();
3200 break;
3202 case END_REACHED:
3203 SAL_WARN(
3204 "basic",
3205 ("ScriptExtensionIterator::nextBasicOrDialogLibrary():"
3206 " Invalid case END_REACHED"));
3207 break;
3211 return aRetLib;
3214 ScriptSubPackageIterator::ScriptSubPackageIterator( Reference< deployment::XPackage > const & xMainPackage )
3215 : m_xMainPackage( xMainPackage )
3216 , m_bIsValid( false )
3217 , m_bIsBundle( false )
3218 , m_nSubPkgCount( 0 )
3219 , m_iNextSubPkg( 0 )
3221 if( !m_xMainPackage.is() )
3223 return;
3225 // Check if parent package is registered
3226 beans::Optional< beans::Ambiguous<sal_Bool> > option( m_xMainPackage->isRegistered
3227 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
3228 bool bRegistered = false;
3229 if( option.IsPresent )
3231 beans::Ambiguous<sal_Bool> const & reg = option.Value;
3232 if( !reg.IsAmbiguous && reg.Value )
3234 bRegistered = true;
3237 if( bRegistered )
3239 m_bIsValid = true;
3240 if( m_xMainPackage->isBundle() )
3242 m_bIsBundle = true;
3243 m_aSubPkgSeq = m_xMainPackage->getBundle( Reference<task::XAbortChannel>(),
3244 Reference<ucb::XCommandEnvironment>() );
3245 m_nSubPkgCount = m_aSubPkgSeq.getLength();
3250 Reference< deployment::XPackage > ScriptSubPackageIterator::getNextScriptSubPackage( bool& rbPureDialogLib )
3252 rbPureDialogLib = false;
3254 Reference< deployment::XPackage > xScriptPackage;
3255 if( !m_bIsValid )
3257 return xScriptPackage;
3259 if( m_bIsBundle )
3261 const Reference< deployment::XPackage >* pSeq = m_aSubPkgSeq.getConstArray();
3262 sal_Int32 iPkg;
3263 for( iPkg = m_iNextSubPkg ; iPkg < m_nSubPkgCount ; ++iPkg )
3265 const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
3266 xScriptPackage = implDetectScriptPackage( xSubPkg, rbPureDialogLib );
3267 if( xScriptPackage.is() )
3269 break;
3272 m_iNextSubPkg = iPkg + 1;
3274 else
3276 xScriptPackage = implDetectScriptPackage( m_xMainPackage, rbPureDialogLib );
3277 m_bIsValid = false; // No more script packages
3280 return xScriptPackage;
3283 Reference< deployment::XPackage > ScriptSubPackageIterator::implDetectScriptPackage ( const Reference< deployment::XPackage >& rPackage,
3284 bool& rbPureDialogLib )
3286 Reference< deployment::XPackage > xScriptPackage;
3288 if( rPackage.is() )
3290 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = rPackage->getPackageType();
3291 OUString aMediaType = xPackageTypeInfo->getMediaType();
3292 if ( aMediaType == sBasicLibMediaType )
3294 xScriptPackage = rPackage;
3296 else if ( aMediaType == sDialogLibMediaType )
3298 rbPureDialogLib = true;
3299 xScriptPackage = rPackage;
3303 return xScriptPackage;
3306 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextUserScriptPackage( bool& rbPureDialogLib )
3308 Reference< deployment::XPackage > xScriptPackage;
3310 if( !m_bUserPackagesLoaded )
3314 Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext );
3315 m_aUserPackagesSeq = xManager->getDeployedExtensions("user",
3316 Reference< task::XAbortChannel >(),
3317 Reference< ucb::XCommandEnvironment >() );
3319 catch(const css::uno::DeploymentException& )
3321 // Special Office installations may not contain deployment code
3322 m_eState = END_REACHED;
3323 return xScriptPackage;
3326 m_bUserPackagesLoaded = true;
3329 if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
3331 m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE
3333 else
3335 if( m_pScriptSubPackageIterator == nullptr )
3337 const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
3338 Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage ];
3339 SAL_WARN_IF(
3340 !xPackage.is(), "basic",
3341 ("ScriptExtensionIterator::implGetNextUserScriptPackage():"
3342 " Invalid package"));
3343 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
3346 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
3347 if( !xScriptPackage.is() )
3349 delete m_pScriptSubPackageIterator;
3350 m_pScriptSubPackageIterator = nullptr;
3351 m_iUserPackage++;
3355 return xScriptPackage;
3358 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextSharedScriptPackage( bool& rbPureDialogLib )
3360 Reference< deployment::XPackage > xScriptPackage;
3362 if( !m_bSharedPackagesLoaded )
3366 Reference< XExtensionManager > xSharedManager = ExtensionManager::get( m_xContext );
3367 m_aSharedPackagesSeq = xSharedManager->getDeployedExtensions("shared",
3368 Reference< task::XAbortChannel >(),
3369 Reference< ucb::XCommandEnvironment >() );
3371 catch(const css::uno::DeploymentException& )
3373 // Special Office installations may not contain deployment code
3374 return xScriptPackage;
3377 m_bSharedPackagesLoaded = true;
3380 if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
3382 m_eState = BUNDLED_EXTENSIONS;
3384 else
3386 if( m_pScriptSubPackageIterator == nullptr )
3388 const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
3389 Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage ];
3390 SAL_WARN_IF(
3391 !xPackage.is(), "basic",
3392 ("ScriptExtensionIterator::implGetNextSharedScriptPackage():"
3393 " Invalid package"));
3394 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
3397 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
3398 if( !xScriptPackage.is() )
3400 delete m_pScriptSubPackageIterator;
3401 m_pScriptSubPackageIterator = nullptr;
3402 m_iSharedPackage++;
3406 return xScriptPackage;
3409 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextBundledScriptPackage( bool& rbPureDialogLib )
3411 Reference< deployment::XPackage > xScriptPackage;
3413 if( !m_bBundledPackagesLoaded )
3417 Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext );
3418 m_aBundledPackagesSeq = xManager->getDeployedExtensions("bundled",
3419 Reference< task::XAbortChannel >(),
3420 Reference< ucb::XCommandEnvironment >() );
3422 catch(const css::uno::DeploymentException& )
3424 // Special Office installations may not contain deployment code
3425 return xScriptPackage;
3428 m_bBundledPackagesLoaded = true;
3431 if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
3433 m_eState = END_REACHED;
3435 else
3437 if( m_pScriptSubPackageIterator == nullptr )
3439 const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray();
3440 Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage ];
3441 SAL_WARN_IF(
3442 !xPackage.is(), "basic",
3443 ("ScriptExtensionIterator::implGetNextBundledScriptPackage():"
3444 " Invalid package"));
3445 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
3448 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
3449 if( !xScriptPackage.is() )
3451 delete m_pScriptSubPackageIterator;
3452 m_pScriptSubPackageIterator = nullptr;
3453 m_iBundledPackage++;
3457 return xScriptPackage;
3460 } // namespace basic
3462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */