xref: /trunk/main/basic/source/uno/scriptcont.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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