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