xref: /aoo41x/main/basic/source/uno/namecont.cxx (revision 0848378b)
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