xref: /trunk/main/basic/source/uno/scriptcont.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 #include "scriptcont.hxx"
31 #include "sbmodule.hxx"
32 #include <com/sun/star/container/XNameContainer.hpp>
33 #include <com/sun/star/xml/sax/XParser.hpp>
34 #include <com/sun/star/xml/sax/InputSource.hpp>
35 #include <com/sun/star/io/XOutputStream.hpp>
36 #include <com/sun/star/io/XInputStream.hpp>
37 #include <com/sun/star/io/XActiveDataSource.hpp>
38 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
39 #include <com/sun/star/embed/ElementModes.hpp>
40 #include <com/sun/star/embed/XEncryptionProtectedSource.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/embed/XTransactedObject.hpp>
43 #include <com/sun/star/task/ErrorCodeIOException.hpp>
44 #include <com/sun/star/script/ModuleType.hpp>
45 #include <comphelper/processfactory.hxx>
46 #ifndef _COMPHELPER_STORAGEHELPER_HXX_
47 #include <comphelper/storagehelper.hxx>
48 #endif
49 #include <unotools/streamwrap.hxx>
50 #include <unotools/ucbstreamhelper.hxx>
51 #include <osl/mutex.hxx>
52 #include <rtl/digest.h>
53 #include <rtl/strbuf.hxx>
54 
55 // For password functionality
56 #include <tools/urlobj.hxx>
57 
58 
59 #include <unotools/pathoptions.hxx>
60 #include <svtools/sfxecode.hxx>
61 #include <svtools/ehdl.hxx>
62 #include <basic/basmgr.hxx>
63 #include <basic/sbmod.hxx>
64 #include <basic/basicmanagerrepository.hxx>
65 #include "basic/modsizeexceeded.hxx"
66 #include <xmlscript/xmlmod_imexp.hxx>
67 #include <cppuhelper/factory.hxx>
68 #include <com/sun/star/util/VetoException.hpp>
69 
70 namespace basic
71 {
72 
73 using namespace com::sun::star::document;
74 using namespace com::sun::star::container;
75 using namespace com::sun::star::io;
76 using namespace com::sun::star::uno;
77 using namespace com::sun::star::ucb;
78 using namespace com::sun::star::lang;
79 using namespace com::sun::star::script;
80 using namespace com::sun::star::xml::sax;
81 using namespace com::sun::star;
82 using namespace cppu;
83 using namespace osl;
84 
85 using ::rtl::OUString;
86 
87 //============================================================================
88 // Implementation class SfxScriptLibraryContainer
89 
90 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getInfoFileName() const { return "script"; }
91 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; }
92 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; }
93 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; }
94 
95 // OldBasicPassword interface
96 void SfxScriptLibraryContainer::setLibraryPassword
97     ( const String& rLibraryName, const String& rPassword )
98 {
99     try
100     {
101         SfxLibrary* pImplLib = getImplLib( rLibraryName );
102         if( rPassword.Len() )
103         {
104 	        pImplLib->mbDoc50Password = sal_True;
105             pImplLib->mbPasswordProtected = sal_True;
106             pImplLib->maPassword = rPassword;
107         }
108     }
109     catch( NoSuchElementException& ) {}
110 }
111 
112 String SfxScriptLibraryContainer::getLibraryPassword( const String& rLibraryName )
113 {
114     SfxLibrary* pImplLib = getImplLib( rLibraryName );
115     String aPassword;
116     if( pImplLib->mbPasswordVerified )
117         aPassword = pImplLib->maPassword;
118     return aPassword;
119 }
120 
121 void SfxScriptLibraryContainer::clearLibraryPassword( const String& rLibraryName )
122 {
123     try
124     {
125         SfxLibrary* pImplLib = getImplLib( rLibraryName );
126 	    pImplLib->mbDoc50Password = sal_False;
127         pImplLib->mbPasswordProtected = sal_False;
128         pImplLib->maPassword = OUString();
129     }
130     catch( NoSuchElementException& ) {}
131 }
132 
133 sal_Bool SfxScriptLibraryContainer::hasLibraryPassword( const String& rLibraryName )
134 {
135     SfxLibrary* pImplLib = getImplLib( rLibraryName );
136     return pImplLib->mbPasswordProtected;
137 }
138 
139 
140 // Ctor for service
141 SfxScriptLibraryContainer::SfxScriptLibraryContainer( void )
142     :maScriptLanguage( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) )
143 {
144     // all initialisation has to be done
145     // by calling XInitialization::initialize
146 }
147 
148 SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference< embed::XStorage >& xStorage )
149     :maScriptLanguage( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) )
150 {
151     init( OUString(), xStorage );
152 }
153 
154 // Methods to get library instances of the correct type
155 SfxLibrary* SfxScriptLibraryContainer::implCreateLibrary( const OUString& aName )
156 {
157 	(void)aName;	// Only needed for SfxDialogLibrary
158 	SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxMSF, mxSFI );
159 	return pRet;
160 }
161 
162 SfxLibrary* SfxScriptLibraryContainer::implCreateLibraryLink
163 	( const OUString& aName, const OUString& aLibInfoFileURL,
164 	  const OUString& StorageURL, sal_Bool ReadOnly )
165 {
166 	(void)aName;	// Only needed for SfxDialogLibrary
167 	SfxLibrary* pRet =
168 		new SfxScriptLibrary
169             ( maModifiable, mxMSF, mxSFI, aLibInfoFileURL, StorageURL, ReadOnly );
170 	return pRet;
171 }
172 
173 Any SAL_CALL SfxScriptLibraryContainer::createEmptyLibraryElement( void )
174 {
175 	OUString aMod;
176 	Any aRetAny;
177 	aRetAny <<= aMod;
178 	return aRetAny;
179 }
180 
181 bool SAL_CALL SfxScriptLibraryContainer::isLibraryElementValid( Any aElement ) const
182 {
183     return SfxScriptLibrary::containsValidModule( aElement );
184 }
185 
186 void SAL_CALL SfxScriptLibraryContainer::writeLibraryElement
187 (
188 	const Reference < XNameContainer >& xLib,
189 	const OUString& aElementName,
190 	const Reference< XOutputStream >& xOutput
191 )
192 	throw(Exception)
193 {
194 	// Create sax writer
195 	Reference< XExtendedDocumentHandler > xHandler(
196 		mxMSF->createInstance(
197 			OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") ) ), UNO_QUERY );
198 	if( !xHandler.is() )
199 	{
200 		OSL_ENSURE( 0, "### couln't create sax-writer component\n" );
201 		return;
202 	}
203 
204 	Reference< XTruncate > xTruncate( xOutput, UNO_QUERY );
205 	OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" );
206 	if ( xTruncate.is() )
207 		xTruncate->truncate();
208 
209 	Reference< XActiveDataSource > xSource( xHandler, UNO_QUERY );
210 	xSource->setOutputStream( xOutput );
211 
212 	xmlscript::ModuleDescriptor aMod;
213 	aMod.aName = aElementName;
214 	aMod.aLanguage = maScriptLanguage;
215 	Any aElement = xLib->getByName( aElementName );
216     aElement >>= aMod.aCode;
217 
218 	Reference< script::vba::XVBAModuleInfo > xModInfo( xLib, UNO_QUERY );
219 	if( xModInfo.is() && xModInfo->hasModuleInfo( aElementName ) )
220 	{
221 		script::ModuleInfo aModInfo = xModInfo->getModuleInfo( aElementName );
222 		switch( aModInfo.ModuleType )
223 		{
224 		case ModuleType::NORMAL:
225 			aMod.aModuleType = OUString( RTL_CONSTASCII_USTRINGPARAM("normal") );
226 			break;
227 		case ModuleType::CLASS:
228 			aMod.aModuleType = OUString( RTL_CONSTASCII_USTRINGPARAM("class") );
229 			break;
230 		case ModuleType::FORM:
231 			aMod.aModuleType = OUString( RTL_CONSTASCII_USTRINGPARAM("form") );
232 			break;
233 		case ModuleType::DOCUMENT:
234 			aMod.aModuleType = OUString( RTL_CONSTASCII_USTRINGPARAM("document") );
235 			break;
236 		case ModuleType::UNKNOWN:
237 			// nothing
238 			break;
239 		}
240 	}
241 
242 	xmlscript::exportScriptModule( xHandler, aMod );
243 }
244 
245 
246 Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement
247 	( const Reference < XNameContainer >& xLib,
248 	  const OUString& aElementName, const OUString& aFile,
249 	  const uno::Reference< io::XInputStream >& xInStream )
250 {
251 	Any aRetAny;
252 
253 	Reference< XParser > xParser( mxMSF->createInstance(
254 		OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY );
255 	if( !xParser.is() )
256 	{
257 		OSL_ENSURE( 0, "### couln't create sax parser component\n" );
258 		return aRetAny;
259 	}
260 
261 
262 	// Read from storage?
263 	sal_Bool bStorage = xInStream.is();
264 	Reference< XInputStream > xInput;
265 
266 	if( bStorage )
267 	{
268 		xInput = xInStream;
269 	}
270 	else
271 	{
272 		try
273 		{
274 			xInput = mxSFI->openFileRead( aFile );
275 		}
276 		catch( Exception& )
277 		//catch( Exception& e )
278 		{
279             // TODO:
280 			//throw WrappedTargetException( e );
281 		}
282 	}
283 
284 	if( !xInput.is() )
285 		return aRetAny;
286 
287 	InputSource source;
288 	source.aInputStream = xInput;
289 	source.sSystemId 	= aFile;
290 
291 	// start parsing
292 	xmlscript::ModuleDescriptor aMod;
293 
294     try
295     {
296     	xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) );
297 	    xParser->parseStream( source );
298     }
299     catch( Exception& )
300     {
301 		SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile );
302         sal_uIntPtr nErrorCode = ERRCODE_IO_GENERAL;
303         ErrorHandler::HandleError( nErrorCode );
304     }
305 
306 	aRetAny <<= aMod.aCode;
307 
308     // TODO: Check language
309 	// aMod.aLanguage
310 	// aMod.aName ignored
311 	if( aMod.aModuleType.getLength() > 0 )
312 	{
313         /*  If in VBA compatibility mode, force creation of the VBA Globals
314             object. Each application will create an instance of its own
315             implementation and store it in its Basic manager. Implementations
316             will do all necessary additional initialization, such as
317             registering the global "This***Doc" UNO constant, starting the
318             document events processor etc.
319          */
320         if( getVBACompatibilityMode() ) try
321         {
322             Reference< frame::XModel > xModel( mxOwnerDocument );   // weak-ref -> ref
323             Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
324             xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) );
325         }
326         catch( Exception& )
327         {
328         }
329 
330 		script::ModuleInfo aModInfo;
331 		aModInfo.ModuleType = ModuleType::UNKNOWN;
332         if( aMod.aModuleType.equalsAsciiL(
333 					RTL_CONSTASCII_STRINGPARAM("normal") ))
334 		{
335             aModInfo.ModuleType = ModuleType::NORMAL;
336 		}
337 		else if( aMod.aModuleType.equalsAsciiL(
338 					RTL_CONSTASCII_STRINGPARAM("class") ))
339 		{
340             aModInfo.ModuleType = ModuleType::CLASS;
341 		}
342 		else if( aMod.aModuleType.equalsAsciiL(
343 					RTL_CONSTASCII_STRINGPARAM("form") ))
344 		{
345             aModInfo.ModuleType = ModuleType::FORM;
346 			aModInfo.ModuleObject = mxOwnerDocument;
347 		}
348 		else if( aMod.aModuleType.equalsAsciiL(
349 					RTL_CONSTASCII_STRINGPARAM("document") ))
350 		{
351             aModInfo.ModuleType = ModuleType::DOCUMENT;
352 
353             // #163691# use the same codename access instance for all document modules
354             if( !mxCodeNameAccess.is() ) try
355             {
356                 Reference<frame::XModel > xModel( mxOwnerDocument );
357                 Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY_THROW );
358                 mxCodeNameAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider" ) ) ), UNO_QUERY );
359             }
360             catch( Exception& ) {}
361 
362 			if( mxCodeNameAccess.is() )
363 			{
364 				try
365 				{
366 					aModInfo.ModuleObject.set( mxCodeNameAccess->getByName( aElementName), uno::UNO_QUERY );
367 				}
368 				catch(uno::Exception&)
369 				{
370 					OSL_TRACE("Failed to get documument object for %s", rtl::OUStringToOString( aElementName, RTL_TEXTENCODING_UTF8 ).getStr() );
371 				}
372 			}
373 		}
374 
375 		Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
376 		if( xVBAModuleInfo.is() )
377 		{
378 			if( xVBAModuleInfo->hasModuleInfo( aElementName ) )
379 				xVBAModuleInfo->removeModuleInfo( aElementName );
380 			xVBAModuleInfo->insertModuleInfo( aElementName, aModInfo );
381 		}
382 	}
383 
384 	return aRetAny;
385 }
386 
387 SfxLibraryContainer* SfxScriptLibraryContainer::createInstanceImpl( void )
388 {
389     return new SfxScriptLibraryContainer();
390 }
391 
392 void SAL_CALL SfxScriptLibraryContainer::importFromOldStorage( const ::rtl::OUString& aFile )
393 {
394     // TODO: move loading from old storage to binary filters?
395     SotStorageRef xStorage = new SotStorage( sal_False, aFile );
396     if( xStorage.Is() && xStorage->GetError() == ERRCODE_NONE )
397     {
398         // We need a BasicManager to avoid problems
399         // StarBASIC* pBas = new StarBASIC();
400         BasicManager* pBasicManager = new BasicManager( *(SotStorage*)xStorage, aFile );
401 
402         // Set info
403         LibraryContainerInfo aInfo( this, NULL, static_cast< OldBasicPassword* >( this ) );
404         pBasicManager->SetLibraryContainerInfo( aInfo );
405 
406         // Now the libraries should be copied to this SfxScriptLibraryContainer
407         BasicManager::LegacyDeleteBasicManager( pBasicManager );
408     }
409 }
410 
411 
412 // Storing with password encryption
413 
414 // Methods XLibraryContainerPassword
415 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString& Name )
416     throw (NoSuchElementException, RuntimeException)
417 {
418     LibraryContainerMethodGuard aGuard( *this );
419     SfxLibrary* pImplLib = getImplLib( Name );
420 	sal_Bool bRet = pImplLib->mbPasswordProtected;
421 	return bRet;
422 }
423 
424 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString& Name )
425     throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
426 {
427     LibraryContainerMethodGuard aGuard( *this );
428     SfxLibrary* pImplLib = getImplLib( Name );
429 	if( !pImplLib->mbPasswordProtected )
430 		throw IllegalArgumentException();
431 	sal_Bool bRet = pImplLib->mbPasswordVerified;
432 	return bRet;
433 }
434 
435 sal_Bool SAL_CALL SfxScriptLibraryContainer::verifyLibraryPassword
436     ( const OUString& Name, const OUString& Password )
437         throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
438 {
439     LibraryContainerMethodGuard aGuard( *this );
440     SfxLibrary* pImplLib = getImplLib( Name );
441 	if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified )
442 		throw IllegalArgumentException();
443 
444     // Test password
445     sal_Bool bSuccess = sal_False;
446     if( pImplLib->mbDoc50Password )
447     {
448         bSuccess = ( Password == pImplLib->maPassword );
449         if( bSuccess )
450             pImplLib->mbPasswordVerified = sal_True;
451     }
452     else
453     {
454         pImplLib->maPassword = Password;
455         bSuccess = implLoadPasswordLibrary( pImplLib, Name, sal_True );
456         if( bSuccess )
457         {
458             // The library gets modified by verifiying the password, because other-
459             // wise for saving the storage would be copied and that doesn't work
460             // with mtg's storages when the password is verified
461             pImplLib->implSetModified( sal_True );
462             pImplLib->mbPasswordVerified = sal_True;
463 
464             // Reload library to get source
465             if( pImplLib->mbLoaded )
466                 implLoadPasswordLibrary( pImplLib, Name );
467         }
468     }
469 	return bSuccess;
470 }
471 
472 void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name,
473     const OUString& OldPassword, const OUString& NewPassword )
474         throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
475 {
476     LibraryContainerMethodGuard aGuard( *this );
477     SfxLibrary* pImplLib = getImplLib( Name );
478     if( OldPassword == NewPassword )
479         return;
480 
481     sal_Bool bOldPassword = ( OldPassword.getLength() > 0 );
482     sal_Bool bNewPassword = ( NewPassword.getLength() > 0 );
483 	sal_Bool bStorage = mxStorage.is() && !pImplLib->mbLink;
484 
485     if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) )
486 		throw IllegalArgumentException();
487 
488     // Library must be loaded
489 	loadLibrary( Name );
490 
491     sal_Bool bKillCryptedFiles = sal_False;
492     sal_Bool bKillUncryptedFiles = sal_False;
493 
494     // Remove or change password?
495     if( bOldPassword )
496     {
497         if( isLibraryPasswordVerified( Name ) )
498         {
499             if( pImplLib->maPassword != OldPassword )
500        		    throw IllegalArgumentException();
501         }
502         else
503         {
504             if( !verifyLibraryPassword( Name, OldPassword ) )
505        		    throw IllegalArgumentException();
506 
507             // Reload library to get source
508             // Should be done in verifyLibraryPassword loadLibrary( Name );
509         }
510 
511         if( !bNewPassword )
512         {
513             pImplLib->mbPasswordProtected = sal_False;
514             pImplLib->mbPasswordVerified = sal_False;
515             pImplLib->maPassword = OUString();
516 
517             maModifiable.setModified( sal_True );
518             pImplLib->implSetModified( sal_True );
519 
520             if( !bStorage && !pImplLib->mbDoc50Password )
521             {
522                 // Store application basic uncrypted
523 				uno::Reference< embed::XStorage > xStorage;
524                 storeLibraries_Impl( xStorage, sal_False );
525                 bKillCryptedFiles = sal_True;
526             }
527         }
528     }
529 
530     // Set new password?
531     if( bNewPassword )
532     {
533         pImplLib->mbPasswordProtected = sal_True;
534         pImplLib->mbPasswordVerified = sal_True;
535         pImplLib->maPassword = NewPassword;
536 
537         maModifiable.setModified( sal_True );
538         pImplLib->implSetModified( sal_True );
539 
540         if( !bStorage && !pImplLib->mbDoc50Password )
541         {
542             // Store applictaion basic crypted
543 			uno::Reference< embed::XStorage > xStorage;
544             storeLibraries_Impl( xStorage, sal_False );
545             bKillUncryptedFiles = sal_True;
546         }
547     }
548 
549     if( bKillCryptedFiles || bKillUncryptedFiles )
550     {
551 	    Sequence< OUString > aElementNames = pImplLib->getElementNames();
552 	    sal_Int32 nNameCount = aElementNames.getLength();
553 	    const OUString* pNames = aElementNames.getConstArray();
554         OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name );
555 		try
556 		{
557 			for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
558 			{
559 				OUString aElementName = pNames[ i ];
560 
561 				INetURLObject aElementInetObj( aLibDirPath );
562 				aElementInetObj.insertName( aElementName, sal_False,
563 					INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
564                 if( bKillUncryptedFiles )
565 				    aElementInetObj.setExtension( maLibElementFileExtension );
566                 else
567 				    aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) );
568 				String aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) );
569 
570 				if( mxSFI->exists( aElementPath ) )
571 					mxSFI->kill( aElementPath );
572 			}
573 		}
574         catch( Exception& ) {}
575     }
576 }
577 
578 
579 void setStreamKey( uno::Reference< io::XStream > xStream, const ::rtl::OUString& aPass )
580 {
581 	uno::Reference< embed::XEncryptionProtectedSource > xEncrStream( xStream, uno::UNO_QUERY );
582 	if ( xEncrStream.is() )
583 		xEncrStream->setEncryptionPassword( aPass );
584 }
585 
586 
587 // Impl methods
588 sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib,
589     const ::rtl::OUString& aName, const uno::Reference< embed::XStorage >& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
590 {
591 	OUString aDummyLocation;
592 	Reference< XSimpleFileAccess > xDummySFA;
593 	return implStorePasswordLibrary( pLib, aName, xStorage, aDummyLocation, xDummySFA, xHandler );
594 }
595 
596 sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName,
597         				const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage,
598 						const ::rtl::OUString& aTargetURL, const Reference< XSimpleFileAccess > xToUseSFI, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
599 {
600     bool bExport = aTargetURL.getLength();
601 
602     BasicManager* pBasicMgr = getBasicManager();
603     OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" );
604     if ( !pBasicMgr )
605         return sal_False;
606 
607     // Only need to handle the export case here,
608     // save/saveas etc are handled in sfxbasemodel::storeSelf &
609     // sfxbasemodel::impl_store
610     uno::Sequence<rtl::OUString> aNames;
611     if ( bExport && pBasicMgr->LegacyPsswdBinaryLimitExceeded(aNames) )
612     {
613         if ( xHandler.is() )
614         {
615             ModuleSizeExceeded* pReq =  new ModuleSizeExceeded( aNames );
616             uno::Reference< task::XInteractionRequest > xReq( pReq );
617             xHandler->handle( xReq );
618             if ( pReq->isAbort() )
619                 throw util::VetoException();
620         }
621     }
622 
623     StarBASIC* pBasicLib = pBasicMgr->GetLib( aName );
624     if( !pBasicLib )
625 	    return sal_False;
626 
627 	Sequence< OUString > aElementNames = pLib->getElementNames();
628 	sal_Int32 nNameCount = aElementNames.getLength();
629 	const OUString* pNames = aElementNames.getConstArray();
630 
631 	sal_Bool bLink = pLib->mbLink;
632 	sal_Bool bStorage = xStorage.is() && !bLink;
633 	if( bStorage )
634 	{
635 		for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
636 		{
637 			OUString aElementName = pNames[ i ];
638 
639             // Write binary image stream
640 	        SbModule* pMod = pBasicLib->FindModule( aElementName );
641 	        if( pMod )
642             {
643 		        //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
644 	            OUString aCodeStreamName = aElementName;
645 		        aCodeStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".bin") );
646 
647 				try {
648                 	uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement(
649 										aCodeStreamName,
650 										embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
651 
652 					if ( !xCodeStream.is() )
653 						throw uno::RuntimeException();
654 
655                     SvMemoryStream aMemStream;
656                     /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
657 
658                     sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
659                     Sequence< sal_Int8 > aBinSeq( nSize );
660                     sal_Int8* pData = aBinSeq.getArray();
661 	                ::rtl_copyMemory( pData, aMemStream.GetData(), nSize );
662 
663                    	Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
664 					if ( !xOut.is() )
665 						throw io::IOException(); // access denied because the stream is readonly
666 
667                    	xOut->writeBytes( aBinSeq );
668     				xOut->closeOutput();
669 				}
670 				catch( uno::Exception& )
671 				{
672                     // TODO: handle error
673 				}
674 		    }
675 
676         	if( pLib->mbPasswordVerified || pLib->mbDoc50Password )
677             {
678 			    /*Any aElement = pLib->getByName( aElementName );*/
679 			    if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
680                 {
681                 #if OSL_DEBUG_LEVEL > 0
682                     ::rtl::OStringBuffer aMessage;
683                     aMessage.append( "invalid library element '" );
684                     aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) );
685                     aMessage.append( "'." );
686 			        OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() );
687                 #endif
688                     continue;
689                 }
690 
691                 OUString aSourceStreamName = aElementName;
692 	            aSourceStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") );
693 
694 				try {
695 					uno::Reference< io::XStream > xSourceStream = xStorage->openStreamElement(
696 																aSourceStreamName,
697 																embed::ElementModes::READWRITE );
698 					uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
699 					if ( !xProps.is() )
700 						throw uno::RuntimeException();
701 
702 				    String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
703 				    OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
704 				    xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
705 
706                     // Set encryption key
707                     setStreamKey( xSourceStream, pLib->maPassword );
708 
709 				    Reference< XOutputStream > xOutput = xSourceStream->getOutputStream();
710 					Reference< XNameContainer > xLib( pLib );
711 				    writeLibraryElement( xLib, aElementName, xOutput );
712 					// writeLibraryElement should have the stream already closed
713 				    // xOutput->closeOutput();
714 			    }
715 				catch( uno::Exception& )
716 				{
717 					OSL_ENSURE( sal_False, "Problem on storing of password library!\n" );
718                     // TODO: error handling
719 				}
720             }
721             else    // !mbPasswordVerified
722             {
723                 // TODO
724                 // What to do if not verified?! In any case it's already loaded here
725             }
726 		}
727 
728 	}
729     // Application libraries have only to be saved if the password
730     // is verified because otherwise they can't be modified
731 	else if( pLib->mbPasswordVerified || bExport )
732 	{
733 		try
734 		{
735 			Reference< XSimpleFileAccess > xSFI = mxSFI;
736 			if( xToUseSFI.is() )
737 				xSFI = xToUseSFI;
738 
739             OUString aLibDirPath;
740 			if( bExport )
741 			{
742 				INetURLObject aInetObj( aTargetURL );
743 				aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
744 				aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
745 
746 				if( !xSFI->isFolder( aLibDirPath ) )
747 					xSFI->createFolder( aLibDirPath );
748 			}
749 			else
750 			{
751 	            aLibDirPath = createAppLibraryFolder( pLib, aName );
752 			}
753 
754 			for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
755 			{
756 				OUString aElementName = pNames[ i ];
757 
758 				INetURLObject aElementInetObj( aLibDirPath );
759 				aElementInetObj.insertName( aElementName, sal_False,
760 					INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
761 				aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) );
762 				String aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
763 
764 				/*Any aElement = pLib->getByName( aElementName );*/
765 				if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
766                 {
767                 #if OSL_DEBUG_LEVEL > 0
768                     ::rtl::OStringBuffer aMessage;
769                     aMessage.append( "invalid library element '" );
770                     aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) );
771                     aMessage.append( "'." );
772 			        OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() );
773                 #endif
774                     continue;
775                 }
776 
777                 try
778                 {
779 					uno::Reference< embed::XStorage > xElementRootStorage =
780 															::comphelper::OStorageHelper::GetStorageFromURL(
781 																	aElementPath,
782 																	embed::ElementModes::READWRITE );
783 					if ( !xElementRootStorage.is() )
784 						throw uno::RuntimeException();
785 
786                 	// Write binary image stream
787                 	SbModule* pMod = pBasicLib->FindModule( aElementName );
788                 	if( pMod )
789                 	{
790 	                	OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
791 
792             	    	uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
793 											aCodeStreamName,
794 											embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
795 
796                         SvMemoryStream aMemStream;
797                         /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
798 
799                         sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
800                         Sequence< sal_Int8 > aBinSeq( nSize );
801                         sal_Int8* pData = aBinSeq.getArray();
802                         ::rtl_copyMemory( pData, aMemStream.GetData(), nSize );
803 
804                 	    Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
805 						if ( xOut.is() )
806 						{
807                         	xOut->writeBytes( aBinSeq );
808 					    	xOut->closeOutput();
809 						}
810                     }
811 
812                 	// Write encrypted source stream
813 	            	OUString aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") );
814 
815             		uno::Reference< io::XStream > xSourceStream;
816 					try
817 					{
818 						xSourceStream = xElementRootStorage->openStreamElement(
819 							aSourceStreamName,
820 							embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
821 
822 						// #87671 Allow encryption
823 						uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY );
824 						OSL_ENSURE( xEncr.is(),
825 									"StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
826 						if ( !xEncr.is() )
827 							throw uno::RuntimeException();
828 						xEncr->setEncryptionPassword( pLib->maPassword );
829 					}
830 					catch( ::com::sun::star::packages::WrongPasswordException& )
831 					{
832 						xSourceStream = xElementRootStorage->openEncryptedStreamElement(
833 							aSourceStreamName,
834 							embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
835 							pLib->maPassword );
836 					}
837 
838 					uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
839 					if ( !xProps.is() )
840 						throw uno::RuntimeException();
841 		            String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
842 		            OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
843 		            xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
844 
845                 	Reference< XOutputStream > xOut = xSourceStream->getOutputStream();
846 					Reference< XNameContainer > xLib( pLib );
847 					writeLibraryElement( xLib, aElementName, xOut );
848 					// i50568: sax writer already closes stream
849 					// xOut->closeOutput();
850 
851 					uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY );
852                     OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" );
853 					if ( !xTransact.is() )
854 						throw uno::RuntimeException();
855 
856 					xTransact->commit();
857 	            }
858 				catch( uno::Exception& )
859 				{
860                     // TODO: handle error
861 				}
862 
863                 // Storage Dtor commits too, that makes problems
864                 // xElementRootStorage->Commit();
865 			}
866 		}
867 		catch( Exception& )
868 		{
869 			//throw e;
870 		}
871 	}
872     return sal_True;
873 }
874 
875 sal_Bool SfxScriptLibraryContainer::implLoadPasswordLibrary
876     ( SfxLibrary* pLib, const OUString& Name, sal_Bool bVerifyPasswordOnly )
877         throw(WrappedTargetException, RuntimeException)
878 {
879 	sal_Bool bRet = sal_True;
880 
881 	sal_Bool bLink = pLib->mbLink;
882 	sal_Bool bStorage = mxStorage.is() && !bLink;
883 
884     // Already loaded? Then only verifiedPassword can change something
885 	SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib );
886     if( pScriptLib->mbLoaded )
887     {
888         if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly &&
889             (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) )
890                 return sal_False;
891     }
892 
893     StarBASIC* pBasicLib = NULL;
894     sal_Bool bLoadBinary = sal_False;
895     if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified )
896     {
897         BasicManager* pBasicMgr = getBasicManager();
898         OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
899         sal_Bool bLoaded = pScriptLib->mbLoaded;
900         pScriptLib->mbLoaded = sal_True;        // Necessary to get lib
901         pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : NULL;
902         pScriptLib->mbLoaded = bLoaded;    // Restore flag
903         if( !pBasicLib )
904 	        return sal_False;
905 
906         bLoadBinary = sal_True;
907         pScriptLib->mbLoadedBinary = sal_True;
908     }
909 
910     sal_Bool bLoadSource = sal_False;
911     if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly )
912     {
913         bLoadSource = sal_True;
914         pScriptLib->mbLoadedSource = sal_True;
915     }
916 
917 	Sequence< OUString > aElementNames = pLib->getElementNames();
918 	sal_Int32 nNameCount = aElementNames.getLength();
919 	const OUString* pNames = aElementNames.getConstArray();
920 
921 	if( bStorage )
922     {
923 		uno::Reference< embed::XStorage > xLibrariesStor;
924 		uno::Reference< embed::XStorage > xLibraryStor;
925 		if( bStorage )
926 		{
927 			try {
928 				xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
929 				if ( !xLibrariesStor.is() )
930 					throw uno::RuntimeException();
931 
932 				xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
933 				if ( !xLibraryStor.is() )
934 					throw uno::RuntimeException();
935 			}
936 			catch( uno::Exception& )
937 			{
938 				OSL_ENSURE( 0, "### couln't open sub storage for library\n" );
939 				return sal_False;
940 			}
941 		}
942 
943 		for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
944 		{
945 			OUString aElementName = pNames[ i ];
946 
947             // Load binary
948             if( bLoadBinary )
949             {
950 	            SbModule* pMod = pBasicLib->FindModule( aElementName );
951                 if( !pMod )
952                 {
953 			        pMod = pBasicLib->MakeModule( aElementName, String() );
954 			        pBasicLib->SetModified( sal_False );
955                 }
956 
957 		        //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
958 	            OUString aCodeStreamName= aElementName;
959 		        aCodeStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".bin") );
960 
961 				try {
962                 	uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement(
963 																						aCodeStreamName,
964 																						embed::ElementModes::READ );
965 					if ( !xCodeStream.is() )
966 						throw uno::RuntimeException();
967 
968 					SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
969 					if ( !pStream || pStream->GetError() )
970 					{
971 						sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
972 						delete pStream;
973 						throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), nError );
974 					}
975 
976                     /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
977                     // TODO: Check return value
978 
979 					delete pStream;
980                 }
981 				catch( uno::Exception& )
982 				{
983                     // TODO: error handling
984 				}
985             }
986 
987             // Load source
988             if( bLoadSource || bVerifyPasswordOnly )
989             {
990                 // Access encrypted source stream
991 	            OUString aSourceStreamName = aElementName;
992 		        aSourceStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") );
993 
994 				try {
995 					uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement(
996 																	aSourceStreamName,
997 																	embed::ElementModes::READ,
998 																	pLib->maPassword );
999 					if ( !xSourceStream.is() )
1000 						throw uno::RuntimeException();
1001 
1002 					// if this point is reached then the password is correct
1003 					if ( !bVerifyPasswordOnly )
1004                     {
1005 						uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1006 						if ( !xInStream.is() )
1007 							throw io::IOException(); // read access denied, seems to be impossible
1008 
1009 						Reference< XNameContainer > xLib( pLib );
1010 			            Any aAny = importLibraryElement( xLib,
1011 										aElementName, aSourceStreamName,
1012 									   	xInStream );
1013 			            if( pLib->hasByName( aElementName ) )
1014                         {
1015                             if( aAny.hasValue() )
1016 				                pLib->maNameContainer.replaceByName( aElementName, aAny );
1017                         }
1018 			            else
1019                         {
1020 				            pLib->maNameContainer.insertByName( aElementName, aAny );
1021                         }
1022                     }
1023                 }
1024 				catch( uno::Exception& )
1025 				{
1026 					bRet = sal_False;
1027 				}
1028             }
1029 		}
1030     }
1031     else
1032     {
1033 		try
1034 		{
1035             OUString aLibDirPath = createAppLibraryFolder( pLib, Name );
1036 
1037 			for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1038 			{
1039 				OUString aElementName = pNames[ i ];
1040 
1041 				INetURLObject aElementInetObj( aLibDirPath );
1042 				aElementInetObj.insertName( aElementName, sal_False,
1043 					INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
1044 				aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) );
1045 				String aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
1046 
1047 				uno::Reference< embed::XStorage > xElementRootStorage;
1048 				try {
1049 					xElementRootStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
1050 																	aElementPath,
1051 																	embed::ElementModes::READ );
1052 				} catch( uno::Exception& )
1053 				{
1054                     // TODO: error handling
1055 				}
1056 
1057 				if ( xElementRootStorage.is() )
1058 				{
1059                     // Load binary
1060                     if( bLoadBinary )
1061                     {
1062 	                    SbModule* pMod = pBasicLib->FindModule( aElementName );
1063                         if( !pMod )
1064                         {
1065 			                pMod = pBasicLib->MakeModule( aElementName, String() );
1066 			                pBasicLib->SetModified( sal_False );
1067                         }
1068 
1069 						try {
1070 		                	OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
1071 							uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
1072 																		aCodeStreamName,
1073 																		embed::ElementModes::READ );
1074 
1075 							SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
1076 							if ( !pStream || pStream->GetError() )
1077 							{
1078 								sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
1079 								delete pStream;
1080 								throw task::ErrorCodeIOException( ::rtl::OUString(),
1081 																	uno::Reference< uno::XInterface >(),
1082 																	nError );
1083 							}
1084 
1085                             /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
1086                             // TODO: Check return value
1087 
1088 							delete pStream;
1089                         }
1090 						catch( uno::Exception& )
1091 						{
1092                             // TODO: error handling
1093 						}
1094                     }
1095 
1096                     // Load source
1097                     if( bLoadSource || bVerifyPasswordOnly )
1098                     {
1099                         // Access encrypted source stream
1100 		                OUString aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") );
1101 						try {
1102 							uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement(
1103 																	aSourceStreamName,
1104 																	embed::ElementModes::READ,
1105 																	pLib->maPassword );
1106 							if ( !xSourceStream.is() )
1107 								throw uno::RuntimeException();
1108 
1109 							if ( !bVerifyPasswordOnly )
1110                             {
1111 								uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1112 								if ( !xInStream.is() )
1113 									throw io::IOException(); // read access denied, seems to be impossible
1114 
1115 								Reference< XNameContainer > xLib( pLib );
1116 			                    Any aAny = importLibraryElement( xLib,
1117 												aElementName,
1118 												aSourceStreamName,
1119 												xInStream );
1120 			                    if( pLib->hasByName( aElementName ) )
1121                                 {
1122                                     if( aAny.hasValue() )
1123 				                        pLib->maNameContainer.replaceByName( aElementName, aAny );
1124                                 }
1125 			                    else
1126                                 {
1127 				                    pLib->maNameContainer.insertByName( aElementName, aAny );
1128                                 }
1129                             }
1130                         }
1131 						catch ( uno::Exception& )
1132 						{
1133 							bRet = sal_False;
1134 						}
1135                     }
1136                 }
1137 			}
1138 
1139 		}
1140 		catch( Exception& )
1141 		{
1142             // TODO
1143 			//throw e;
1144 		}
1145     }
1146 
1147 //REMOVE	    // If the password is verified the library must remain modified, because
1148 //REMOVE	    // otherwise for saving the storage would be copied and that doesn't work
1149 //REMOVE	    // with mtg's storages when the password is verified
1150 //REMOVE	    if( !pLib->mbPasswordVerified )
1151 //REMOVE	        pLib->mbModified = sal_False;
1152     return bRet;
1153 }
1154 
1155 
1156 void SfxScriptLibraryContainer::onNewRootStorage()
1157 {
1158 }
1159 
1160 //============================================================================
1161 // Service
1162 void createRegistryInfo_SfxScriptLibraryContainer()
1163 {
1164     static OAutoRegistration< SfxScriptLibraryContainer > aAutoRegistration;
1165 }
1166 
1167 ::rtl::OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( ) throw (RuntimeException)
1168 {
1169     return getImplementationName_static();
1170 }
1171 
1172 Sequence< ::rtl::OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( ) throw (RuntimeException)
1173 {
1174     return getSupportedServiceNames_static();
1175 }
1176 
1177 Sequence< OUString > SfxScriptLibraryContainer::getSupportedServiceNames_static()
1178 {
1179     Sequence< OUString > aServiceNames( 2 );
1180     aServiceNames[0] = OUString::createFromAscii( "com.sun.star.script.DocumentScriptLibraryContainer" );
1181     // plus, for compatibility:
1182     aServiceNames[1] = OUString::createFromAscii( "com.sun.star.script.ScriptLibraryContainer" );
1183     return aServiceNames;
1184 }
1185 
1186 OUString SfxScriptLibraryContainer::getImplementationName_static()
1187 {
1188     static OUString aImplName;
1189     static sal_Bool bNeedsInit = sal_True;
1190 
1191 	MutexGuard aGuard( Mutex::getGlobalMutex() );
1192     if( bNeedsInit )
1193     {
1194         aImplName = OUString::createFromAscii( "com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1195         bNeedsInit = sal_False;
1196     }
1197     return aImplName;
1198 }
1199 
1200 Reference< XInterface > SAL_CALL SfxScriptLibraryContainer::Create
1201     ( const Reference< XComponentContext >& )
1202         throw( Exception )
1203 {
1204     Reference< XInterface > xRet =
1205         static_cast< XInterface* >( static_cast< OWeakObject* >(new SfxScriptLibraryContainer()) );
1206     return xRet;
1207 }
1208 
1209 //============================================================================
1210 // Implementation class SfxScriptLibrary
1211 
1212 // Ctor
1213 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1214                                     const Reference< XMultiServiceFactory >& xMSF,
1215                                     const Reference< XSimpleFileAccess >& xSFI )
1216 	: SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI )
1217     , mbLoadedSource( sal_False )
1218     , mbLoadedBinary( sal_False )
1219 {
1220 }
1221 
1222 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1223                                     const Reference< XMultiServiceFactory >& xMSF,
1224                                     const Reference< XSimpleFileAccess >& xSFI,
1225                                     const OUString& aLibInfoFileURL,
1226                                     const OUString& aStorageURL,
1227                                     sal_Bool ReadOnly )
1228 	: SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI,
1229 						aLibInfoFileURL, aStorageURL, ReadOnly)
1230     , mbLoadedSource( sal_False )
1231     , mbLoadedBinary( sal_False )
1232 {
1233 }
1234 
1235 // Provide modify state including resources
1236 sal_Bool SfxScriptLibrary::isModified( void )
1237 {
1238 	return implIsModified();	// No resources
1239 }
1240 
1241 void SfxScriptLibrary::storeResources( void )
1242 {
1243 	// No resources
1244 }
1245 
1246 void SfxScriptLibrary::storeResourcesToURL( const ::rtl::OUString& URL,
1247 	const Reference< task::XInteractionHandler >& Handler )
1248 {
1249 	(void)URL;
1250 	(void)Handler;
1251 }
1252 
1253 void SfxScriptLibrary::storeResourcesAsURL
1254 	( const ::rtl::OUString& URL, const ::rtl::OUString& NewName )
1255 {
1256 	(void)URL;
1257 	(void)NewName;
1258 }
1259 
1260 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1261 	< ::com::sun::star::embed::XStorage >& xStorage )
1262 {
1263 	// No resources
1264 	(void)xStorage;
1265 }
1266 
1267 bool SfxScriptLibrary::containsValidModule( const Any& aElement )
1268 {
1269 	OUString sModuleText;
1270     aElement >>= sModuleText;
1271 	return ( sModuleText.getLength() > 0 );
1272 }
1273 
1274 bool SAL_CALL SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const
1275 {
1276     return SfxScriptLibrary::containsValidModule( aElement );
1277 }
1278 
1279 IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1280 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1281 
1282 script::ModuleInfo SAL_CALL
1283 SfxScriptLibrary::getModuleInfo( const ::rtl::OUString& ModuleName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
1284 {
1285     if ( !hasModuleInfo( ModuleName ) )
1286         throw NoSuchElementException();
1287     return mModuleInfos[ ModuleName ];
1288 }
1289 
1290 sal_Bool SAL_CALL
1291 SfxScriptLibrary::hasModuleInfo( const ::rtl::OUString& ModuleName ) throw (RuntimeException)
1292 {
1293     sal_Bool bRes = sal_False;
1294     ModuleInfoMap::iterator it = mModuleInfos.find( ModuleName );
1295 
1296     if ( it != mModuleInfos.end() )
1297         bRes = sal_True;
1298 
1299     return bRes;
1300 }
1301 
1302 void SAL_CALL SfxScriptLibrary::insertModuleInfo( const ::rtl::OUString& ModuleName, const script::ModuleInfo& ModuleInfo ) throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
1303 {
1304     if ( hasModuleInfo( ModuleName ) )
1305         throw ElementExistException();
1306     mModuleInfos[ ModuleName ] = ModuleInfo;
1307 }
1308 
1309 void SAL_CALL SfxScriptLibrary::removeModuleInfo( const ::rtl::OUString& ModuleName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
1310 {
1311         // #FIXME add NoSuchElementException to the spec
1312     if ( !hasModuleInfo( ModuleName ) )
1313         throw NoSuchElementException();
1314     mModuleInfos.erase( mModuleInfos.find( ModuleName ) );
1315 }
1316 
1317 
1318 //============================================================================
1319 
1320 }   // namespace basic
1321