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