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