update credits
[LibreOffice.git] / basic / source / uno / scriptcont.cxx
blob793577fb077dad02bf7462ed3c63b46210fa932b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scriptcont.hxx"
21 #include "sbmodule.hxx"
22 #include <com/sun/star/container/XNameContainer.hpp>
23 #include <com/sun/star/xml/sax/Parser.hpp>
24 #include <com/sun/star/xml/sax/InputSource.hpp>
25 #include <com/sun/star/xml/sax/Writer.hpp>
26 #include <com/sun/star/io/XOutputStream.hpp>
27 #include <com/sun/star/io/XInputStream.hpp>
28 #include <com/sun/star/io/XActiveDataSource.hpp>
29 #include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <com/sun/star/embed/XEncryptionProtectedSource.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/embed/XTransactedObject.hpp>
34 #include <com/sun/star/task/ErrorCodeIOException.hpp>
35 #include <com/sun/star/script/ModuleType.hpp>
36 #include <comphelper/componentcontext.hxx>
37 #include <comphelper/processfactory.hxx>
38 #include <comphelper/storagehelper.hxx>
39 #include <unotools/streamwrap.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <osl/mutex.hxx>
42 #include <rtl/digest.h>
43 #include <rtl/strbuf.hxx>
45 // For password functionality
46 #include <tools/urlobj.hxx>
49 #include <unotools/pathoptions.hxx>
50 #include <svtools/sfxecode.hxx>
51 #include <svtools/ehdl.hxx>
52 #include <basic/basmgr.hxx>
53 #include <basic/sbmod.hxx>
54 #include <basic/basicmanagerrepository.hxx>
55 #include "basic/modsizeexceeded.hxx"
56 #include <xmlscript/xmlmod_imexp.hxx>
57 #include <cppuhelper/factory.hxx>
58 #include <com/sun/star/util/VetoException.hpp>
59 #include <com/sun/star/script/XLibraryQueryExecutable.hpp>
60 #include <cppuhelper/implbase1.hxx>
61 namespace basic
64 using namespace com::sun::star::document;
65 using namespace com::sun::star::container;
66 using namespace com::sun::star::io;
67 using namespace com::sun::star::uno;
68 using namespace com::sun::star::ucb;
69 using namespace com::sun::star::lang;
70 using namespace com::sun::star::script;
71 using namespace com::sun::star::xml::sax;
72 using namespace com::sun::star;
73 using namespace cppu;
74 using namespace osl;
76 //============================================================================
77 // Implementation class SfxScriptLibraryContainer
79 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getInfoFileName() const { return "script"; }
80 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; }
81 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; }
82 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; }
84 // OldBasicPassword interface
85 void SfxScriptLibraryContainer::setLibraryPassword( const OUString& rLibraryName, const OUString& rPassword )
87 try
89 SfxLibrary* pImplLib = getImplLib( rLibraryName );
90 if( !rPassword.isEmpty() )
92 pImplLib->mbDoc50Password = true;
93 pImplLib->mbPasswordProtected = sal_True;
94 pImplLib->maPassword = rPassword;
97 catch(const NoSuchElementException& ) {}
100 OUString SfxScriptLibraryContainer::getLibraryPassword( const OUString& rLibraryName )
102 SfxLibrary* pImplLib = getImplLib( rLibraryName );
103 OUString aPassword;
104 if( pImplLib->mbPasswordVerified )
106 aPassword = pImplLib->maPassword;
108 return aPassword;
111 void SfxScriptLibraryContainer::clearLibraryPassword( const OUString& rLibraryName )
115 SfxLibrary* pImplLib = getImplLib( rLibraryName );
116 pImplLib->mbDoc50Password = false;
117 pImplLib->mbPasswordProtected = sal_False;
118 pImplLib->maPassword = OUString();
120 catch(const NoSuchElementException& ) {}
123 sal_Bool SfxScriptLibraryContainer::hasLibraryPassword( const OUString& rLibraryName )
125 SfxLibrary* pImplLib = getImplLib( rLibraryName );
126 return pImplLib->mbPasswordProtected;
129 // Ctor for service
130 SfxScriptLibraryContainer::SfxScriptLibraryContainer( void )
131 :maScriptLanguage( "StarBasic" )
133 // all initialisation has to be done
134 // by calling XInitialization::initialize
137 SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference< embed::XStorage >& xStorage )
138 :maScriptLanguage( "StarBasic" )
140 init( OUString(), xStorage );
143 // Methods to get library instances of the correct type
144 SfxLibrary* SfxScriptLibraryContainer::implCreateLibrary( const OUString& aName )
146 (void)aName; // Only needed for SfxDialogLibrary
147 SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxContext, mxSFI );
148 return pRet;
151 SfxLibrary* SfxScriptLibraryContainer::implCreateLibraryLink( const OUString& aName,
152 const OUString& aLibInfoFileURL,
153 const OUString& StorageURL,
154 sal_Bool ReadOnly )
156 (void)aName; // Only needed for SfxDialogLibrary
157 SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxContext, mxSFI,
158 aLibInfoFileURL, StorageURL, ReadOnly );
159 return pRet;
162 Any SAL_CALL SfxScriptLibraryContainer::createEmptyLibraryElement( void )
164 OUString aMod;
165 Any aRetAny;
166 aRetAny <<= aMod;
167 return aRetAny;
170 bool SAL_CALL SfxScriptLibraryContainer::isLibraryElementValid( Any aElement ) const
172 return SfxScriptLibrary::containsValidModule( aElement );
175 void SAL_CALL SfxScriptLibraryContainer::writeLibraryElement( const Reference < XNameContainer >& xLib,
176 const OUString& aElementName,
177 const Reference< XOutputStream >& xOutput)
178 throw(Exception)
180 // Create sax writer
181 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
183 Reference< XTruncate > xTruncate( xOutput, UNO_QUERY );
184 OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" );
185 if ( xTruncate.is() )
187 xTruncate->truncate();
189 xWriter->setOutputStream( xOutput );
191 xmlscript::ModuleDescriptor aMod;
192 aMod.aName = aElementName;
193 aMod.aLanguage = maScriptLanguage;
194 Any aElement = xLib->getByName( aElementName );
195 aElement >>= aMod.aCode;
197 Reference< script::vba::XVBAModuleInfo > xModInfo( xLib, UNO_QUERY );
198 if( xModInfo.is() && xModInfo->hasModuleInfo( aElementName ) )
200 script::ModuleInfo aModInfo = xModInfo->getModuleInfo( aElementName );
201 switch( aModInfo.ModuleType )
203 case ModuleType::NORMAL:
204 aMod.aModuleType = "normal";
205 break;
206 case ModuleType::CLASS:
207 aMod.aModuleType ="class";
208 break;
209 case ModuleType::FORM:
210 aMod.aModuleType = "form";
211 break;
212 case ModuleType::DOCUMENT:
213 aMod.aModuleType = "document";
214 break;
215 case ModuleType::UNKNOWN:
216 // nothing
217 break;
221 xmlscript::exportScriptModule( xWriter, aMod );
225 Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement
226 ( const Reference < XNameContainer >& xLib,
227 const OUString& aElementName, const OUString& aFile,
228 const uno::Reference< io::XInputStream >& xInStream )
230 Any aRetAny;
232 Reference< XParser > xParser = xml::sax::Parser::create( mxContext );
234 // Read from storage?
235 sal_Bool bStorage = xInStream.is();
236 Reference< XInputStream > xInput;
238 if( bStorage )
240 xInput = xInStream;
242 else
246 xInput = mxSFI->openFileRead( aFile );
248 catch(const Exception& )
249 //catch( Exception& e )
251 // TODO:
252 //throw WrappedTargetException( e );
256 if( !xInput.is() )
257 return aRetAny;
259 InputSource source;
260 source.aInputStream = xInput;
261 source.sSystemId = aFile;
263 // start parsing
264 xmlscript::ModuleDescriptor aMod;
268 xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) );
269 xParser->parseStream( source );
271 catch(const Exception& )
273 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile );
274 sal_uIntPtr nErrorCode = ERRCODE_IO_GENERAL;
275 ErrorHandler::HandleError( nErrorCode );
278 aRetAny <<= aMod.aCode;
280 // TODO: Check language
281 // aMod.aLanguage
282 // aMod.aName ignored
283 if( !aMod.aModuleType.isEmpty() )
285 /* If in VBA compatibility mode, force creation of the VBA Globals
286 object. Each application will create an instance of its own
287 implementation and store it in its Basic manager. Implementations
288 will do all necessary additional initialization, such as
289 registering the global "This***Doc" UNO constant, starting the
290 document events processor etc.
292 if( getVBACompatibilityMode() ) try
294 Reference< frame::XModel > xModel( mxOwnerDocument ); // weak-ref -> ref
295 Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
296 xFactory->createInstance( OUString( "ooo.vba.VBAGlobals" ) );
298 catch(const Exception& )
302 script::ModuleInfo aModInfo;
303 aModInfo.ModuleType = ModuleType::UNKNOWN;
304 if( aMod.aModuleType == "normal" )
306 aModInfo.ModuleType = ModuleType::NORMAL;
308 else if( aMod.aModuleType == "class" )
310 aModInfo.ModuleType = ModuleType::CLASS;
312 else if( aMod.aModuleType == "form" )
314 aModInfo.ModuleType = ModuleType::FORM;
315 aModInfo.ModuleObject = mxOwnerDocument;
317 else if( aMod.aModuleType == "document" )
319 aModInfo.ModuleType = ModuleType::DOCUMENT;
321 // #163691# use the same codename access instance for all document modules
322 if( !mxCodeNameAccess.is() ) try
324 Reference<frame::XModel > xModel( mxOwnerDocument );
325 Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY_THROW );
326 mxCodeNameAccess.set( xSF->createInstance( OUString("ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY );
328 catch(const Exception& ) {}
330 if( mxCodeNameAccess.is() )
334 aModInfo.ModuleObject.set( mxCodeNameAccess->getByName( aElementName), uno::UNO_QUERY );
336 catch(const uno::Exception&)
338 OSL_TRACE("Failed to get documument object for %s", OUStringToOString( aElementName, RTL_TEXTENCODING_UTF8 ).getStr() );
343 Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
344 if( xVBAModuleInfo.is() )
346 if( xVBAModuleInfo->hasModuleInfo( aElementName ) )
348 xVBAModuleInfo->removeModuleInfo( aElementName );
350 xVBAModuleInfo->insertModuleInfo( aElementName, aModInfo );
354 return aRetAny;
357 SfxLibraryContainer* SfxScriptLibraryContainer::createInstanceImpl( void )
359 return new SfxScriptLibraryContainer();
362 void SAL_CALL SfxScriptLibraryContainer::importFromOldStorage( const OUString& aFile )
364 // TODO: move loading from old storage to binary filters?
365 SotStorageRef xStorage = new SotStorage( sal_False, aFile );
366 if( xStorage.Is() && xStorage->GetError() == ERRCODE_NONE )
368 BasicManager* pBasicManager = new BasicManager( *(SotStorage*)xStorage, aFile );
370 // Set info
371 LibraryContainerInfo aInfo( this, NULL, static_cast< OldBasicPassword* >( this ) );
372 pBasicManager->SetLibraryContainerInfo( aInfo );
374 // Now the libraries should be copied to this SfxScriptLibraryContainer
375 BasicManager::LegacyDeleteBasicManager( pBasicManager );
380 // Storing with password encryption
382 // Methods XLibraryContainerPassword
383 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString& Name )
384 throw (NoSuchElementException, RuntimeException)
386 LibraryContainerMethodGuard aGuard( *this );
387 SfxLibrary* pImplLib = getImplLib( Name );
388 sal_Bool bRet = pImplLib->mbPasswordProtected;
389 return bRet;
392 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString& Name )
393 throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
395 LibraryContainerMethodGuard aGuard( *this );
396 SfxLibrary* pImplLib = getImplLib( Name );
397 if( !pImplLib->mbPasswordProtected )
399 throw IllegalArgumentException();
401 sal_Bool bRet = pImplLib->mbPasswordVerified;
402 return bRet;
405 sal_Bool SAL_CALL SfxScriptLibraryContainer::verifyLibraryPassword
406 ( const OUString& Name, const OUString& Password )
407 throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
409 LibraryContainerMethodGuard aGuard( *this );
410 SfxLibrary* pImplLib = getImplLib( Name );
411 if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified )
413 throw IllegalArgumentException();
415 // Test password
416 sal_Bool bSuccess = sal_False;
417 if( pImplLib->mbDoc50Password )
419 bSuccess = ( Password == pImplLib->maPassword );
420 if( bSuccess )
422 pImplLib->mbPasswordVerified = sal_True;
425 else
427 pImplLib->maPassword = Password;
428 bSuccess = implLoadPasswordLibrary( pImplLib, Name, sal_True );
429 if( bSuccess )
431 // The library gets modified by verifiying the password, because other-
432 // wise for saving the storage would be copied and that doesn't work
433 // with mtg's storages when the password is verified
434 pImplLib->implSetModified( sal_True );
435 pImplLib->mbPasswordVerified = sal_True;
437 // Reload library to get source
438 if( pImplLib->mbLoaded )
440 implLoadPasswordLibrary( pImplLib, Name );
444 return bSuccess;
447 void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name,
448 const OUString& OldPassword,
449 const OUString& NewPassword )
450 throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
452 LibraryContainerMethodGuard aGuard( *this );
453 SfxLibrary* pImplLib = getImplLib( Name );
454 if( OldPassword == NewPassword )
456 return;
458 sal_Bool bOldPassword = !OldPassword.isEmpty();
459 sal_Bool bNewPassword = !NewPassword.isEmpty();
460 sal_Bool bStorage = mxStorage.is() && !pImplLib->mbLink;
462 if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) )
464 throw IllegalArgumentException();
466 // Library must be loaded
467 loadLibrary( Name );
469 sal_Bool bKillCryptedFiles = sal_False;
470 sal_Bool bKillUncryptedFiles = sal_False;
472 // Remove or change password?
473 if( bOldPassword )
475 if( isLibraryPasswordVerified( Name ) )
477 if( pImplLib->maPassword != OldPassword )
479 throw IllegalArgumentException();
482 else
484 if( !verifyLibraryPassword( Name, OldPassword ) )
486 throw IllegalArgumentException();
488 // Reload library to get source
489 // Should be done in verifyLibraryPassword loadLibrary( Name );
492 if( !bNewPassword )
494 pImplLib->mbPasswordProtected = sal_False;
495 pImplLib->mbPasswordVerified = sal_False;
496 pImplLib->maPassword = OUString();
498 maModifiable.setModified( sal_True );
499 pImplLib->implSetModified( sal_True );
501 if( !bStorage && !pImplLib->mbDoc50Password )
503 // Store application basic uncrypted
504 uno::Reference< embed::XStorage > xStorage;
505 storeLibraries_Impl( xStorage, false );
506 bKillCryptedFiles = sal_True;
511 // Set new password?
512 if( bNewPassword )
514 pImplLib->mbPasswordProtected = sal_True;
515 pImplLib->mbPasswordVerified = sal_True;
516 pImplLib->maPassword = NewPassword;
518 maModifiable.setModified( sal_True );
519 pImplLib->implSetModified( sal_True );
521 if( !bStorage && !pImplLib->mbDoc50Password )
523 // Store applictaion basic crypted
524 uno::Reference< embed::XStorage > xStorage;
525 storeLibraries_Impl( xStorage, false );
526 bKillUncryptedFiles = sal_True;
530 if( bKillCryptedFiles || bKillUncryptedFiles )
532 Sequence< OUString > aElementNames = pImplLib->getElementNames();
533 sal_Int32 nNameCount = aElementNames.getLength();
534 const OUString* pNames = aElementNames.getConstArray();
535 OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name );
538 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
540 OUString aElementName = pNames[ i ];
542 INetURLObject aElementInetObj( aLibDirPath );
543 aElementInetObj.insertName( aElementName, sal_False,
544 INetURLObject::LAST_SEGMENT, sal_True,
545 INetURLObject::ENCODE_ALL );
546 if( bKillUncryptedFiles )
548 aElementInetObj.setExtension( maLibElementFileExtension );
550 else
552 aElementInetObj.setExtension( OUString( "pba" ) );
554 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) );
556 if( mxSFI->exists( aElementPath ) )
558 mxSFI->kill( aElementPath );
562 catch(const Exception& ) {}
567 void setStreamKey( uno::Reference< io::XStream > xStream, const OUString& aPass )
569 uno::Reference< embed::XEncryptionProtectedSource > xEncrStream( xStream, uno::UNO_QUERY );
570 if ( xEncrStream.is() )
572 xEncrStream->setEncryptionPassword( aPass );
577 // Impl methods
578 sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib,
579 const OUString& aName,
580 const uno::Reference< embed::XStorage >& xStorage,
581 const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
583 OUString aDummyLocation;
584 Reference< XSimpleFileAccess3 > xDummySFA;
585 return implStorePasswordLibrary( pLib, aName, xStorage, aDummyLocation, xDummySFA, xHandler );
588 sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const OUString& aName,
589 const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage,
590 const OUString& aTargetURL,
591 const Reference< XSimpleFileAccess3 > xToUseSFI,
592 const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
594 bool bExport = !aTargetURL.isEmpty();
596 BasicManager* pBasicMgr = getBasicManager();
597 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" );
598 if ( !pBasicMgr )
600 return sal_False;
602 // Only need to handle the export case here,
603 // save/saveas etc are handled in sfxbasemodel::storeSelf &
604 // sfxbasemodel::impl_store
605 uno::Sequence<OUString> aNames;
606 if ( bExport && pBasicMgr->LegacyPsswdBinaryLimitExceeded(aNames) )
608 if ( xHandler.is() )
610 ModuleSizeExceeded* pReq = new ModuleSizeExceeded( aNames );
611 uno::Reference< task::XInteractionRequest > xReq( pReq );
612 xHandler->handle( xReq );
613 if ( pReq->isAbort() )
615 throw util::VetoException();
620 StarBASIC* pBasicLib = pBasicMgr->GetLib( aName );
621 if( !pBasicLib )
623 return sal_False;
625 Sequence< OUString > aElementNames = pLib->getElementNames();
626 sal_Int32 nNameCount = aElementNames.getLength();
627 const OUString* pNames = aElementNames.getConstArray();
629 sal_Bool bLink = pLib->mbLink;
630 sal_Bool bStorage = xStorage.is() && !bLink;
631 if( bStorage )
633 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
635 OUString aElementName = pNames[ i ];
637 // Write binary image stream
638 SbModule* pMod = pBasicLib->FindModule( aElementName );
639 if( pMod )
641 OUString aCodeStreamName = aElementName;
642 aCodeStreamName += ".bin";
646 uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement(
647 aCodeStreamName,
648 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
650 if ( !xCodeStream.is() )
652 throw uno::RuntimeException();
654 SvMemoryStream aMemStream;
655 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
657 sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
658 Sequence< sal_Int8 > aBinSeq( nSize );
659 sal_Int8* pData = aBinSeq.getArray();
660 memcpy( pData, aMemStream.GetData(), nSize );
662 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
663 if ( !xOut.is() )
665 throw io::IOException(); // access denied because the stream is readonly
667 xOut->writeBytes( aBinSeq );
668 xOut->closeOutput();
670 catch(const uno::Exception& )
672 // TODO: handle error
676 if( pLib->mbPasswordVerified || pLib->mbDoc50Password )
678 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
680 #if OSL_DEBUG_LEVEL > 0
681 OString aMessage = "invalid library element '" +
682 OUStringToOString( aElementName, osl_getThreadTextEncoding() ) +
683 "'.";
684 OSL_FAIL( aMessage.getStr());
685 #endif
686 continue;
689 OUString aSourceStreamName = aElementName;
690 aSourceStreamName += ".xml";
694 uno::Reference< io::XStream > xSourceStream = xStorage->openStreamElement(
695 aSourceStreamName,
696 embed::ElementModes::READWRITE );
697 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
698 if ( !xProps.is() )
700 throw uno::RuntimeException();
702 OUString aMime( "text/xml" );
703 xProps->setPropertyValue( OUString("MediaType"), uno::makeAny( aMime ) );
705 // Set encryption key
706 setStreamKey( xSourceStream, pLib->maPassword );
708 Reference< XOutputStream > xOutput = xSourceStream->getOutputStream();
709 Reference< XNameContainer > xLib( pLib );
710 writeLibraryElement( xLib, aElementName, xOutput );
712 catch(const uno::Exception& )
714 OSL_FAIL( "Problem on storing of password library!\n" );
715 // TODO: error handling
718 else // !mbPasswordVerified
720 // TODO
721 // What to do if not verified?! In any case it's already loaded here
726 // Application libraries have only to be saved if the password
727 // is verified because otherwise they can't be modified
728 else if( pLib->mbPasswordVerified || bExport )
732 Reference< XSimpleFileAccess3 > xSFI = mxSFI;
733 if( xToUseSFI.is() )
735 xSFI = xToUseSFI;
737 OUString aLibDirPath;
738 if( bExport )
740 INetURLObject aInetObj( aTargetURL );
741 aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True,
742 INetURLObject::ENCODE_ALL );
743 aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
745 if( !xSFI->isFolder( aLibDirPath ) )
747 xSFI->createFolder( aLibDirPath );
750 else
752 aLibDirPath = createAppLibraryFolder( pLib, aName );
755 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
757 OUString aElementName = pNames[ i ];
759 INetURLObject aElementInetObj( aLibDirPath );
760 aElementInetObj.insertName( aElementName, sal_False,
761 INetURLObject::LAST_SEGMENT, sal_True,
762 INetURLObject::ENCODE_ALL );
763 aElementInetObj.setExtension( OUString( "pba" ) );
764 OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
766 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
768 #if OSL_DEBUG_LEVEL > 0
769 OString aMessage = "invalid library element '" +
770 OUStringToOString( aElementName, osl_getThreadTextEncoding() ) +
771 "'.";
772 OSL_FAIL( aMessage.getStr());
773 #endif
774 continue;
779 uno::Reference< embed::XStorage > xElementRootStorage =
780 ::comphelper::OStorageHelper::GetStorageFromURL(
781 aElementPath,
782 embed::ElementModes::READWRITE );
783 if ( !xElementRootStorage.is() )
785 throw uno::RuntimeException();
787 // Write binary image stream
788 SbModule* pMod = pBasicLib->FindModule( aElementName );
789 if( pMod )
791 OUString aCodeStreamName( "code.bin" );
793 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
794 aCodeStreamName,
795 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
797 SvMemoryStream aMemStream;
798 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
800 sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
801 Sequence< sal_Int8 > aBinSeq( nSize );
802 sal_Int8* pData = aBinSeq.getArray();
803 memcpy( pData, aMemStream.GetData(), nSize );
805 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
806 if ( xOut.is() )
808 xOut->writeBytes( aBinSeq );
809 xOut->closeOutput();
813 // Write encrypted source stream
814 OUString aSourceStreamName( "source.xml" );
816 uno::Reference< io::XStream > xSourceStream;
819 xSourceStream = xElementRootStorage->openStreamElement(
820 aSourceStreamName,
821 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
823 // #87671 Allow encryption
824 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY );
825 OSL_ENSURE( xEncr.is(),
826 "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
827 if ( !xEncr.is() )
829 throw uno::RuntimeException();
831 xEncr->setEncryptionPassword( pLib->maPassword );
833 catch(const ::com::sun::star::packages::WrongPasswordException& )
835 xSourceStream = xElementRootStorage->openEncryptedStreamElement(
836 aSourceStreamName,
837 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
838 pLib->maPassword );
841 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
842 if ( !xProps.is() )
844 throw uno::RuntimeException();
846 OUString aMime( "text/xml" );
847 xProps->setPropertyValue( OUString("MediaType"), uno::makeAny( aMime ) );
849 Reference< XOutputStream > xOut = xSourceStream->getOutputStream();
850 Reference< XNameContainer > xLib( pLib );
851 writeLibraryElement( xLib, aElementName, xOut );
852 // i50568: sax writer already closes stream
853 // xOut->closeOutput();
855 uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY );
856 OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" );
857 if ( !xTransact.is() )
859 throw uno::RuntimeException();
862 xTransact->commit();
864 catch(const uno::Exception& )
866 // TODO: handle error
871 catch(const Exception& )
875 return sal_True;
878 sal_Bool SfxScriptLibraryContainer::implLoadPasswordLibrary
879 ( SfxLibrary* pLib, const OUString& Name, sal_Bool bVerifyPasswordOnly )
880 throw(WrappedTargetException, RuntimeException)
882 sal_Bool bRet = sal_True;
884 sal_Bool bLink = pLib->mbLink;
885 sal_Bool bStorage = mxStorage.is() && !bLink;
887 // Already loaded? Then only verifiedPassword can change something
888 SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib );
889 if( pScriptLib->mbLoaded )
891 if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly &&
892 (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) )
894 return sal_False;
898 StarBASIC* pBasicLib = NULL;
899 sal_Bool bLoadBinary = sal_False;
900 if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified )
902 BasicManager* pBasicMgr = getBasicManager();
903 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
904 sal_Bool bLoaded = pScriptLib->mbLoaded;
905 pScriptLib->mbLoaded = sal_True; // Necessary to get lib
906 pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : NULL;
907 pScriptLib->mbLoaded = bLoaded; // Restore flag
908 if( !pBasicLib )
910 return sal_False;
912 bLoadBinary = sal_True;
913 pScriptLib->mbLoadedBinary = true;
916 sal_Bool bLoadSource = sal_False;
917 if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly )
919 bLoadSource = sal_True;
920 pScriptLib->mbLoadedSource = true;
923 Sequence< OUString > aElementNames = pLib->getElementNames();
924 sal_Int32 nNameCount = aElementNames.getLength();
925 const OUString* pNames = aElementNames.getConstArray();
927 if( bStorage )
929 uno::Reference< embed::XStorage > xLibrariesStor;
930 uno::Reference< embed::XStorage > xLibraryStor;
931 if( bStorage )
933 try {
934 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
935 if ( !xLibrariesStor.is() )
937 throw uno::RuntimeException();
939 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
940 if ( !xLibraryStor.is() )
942 throw uno::RuntimeException();
945 catch(const uno::Exception& )
947 OSL_FAIL( "### couldn't open sub storage for library\n" );
948 return sal_False;
952 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
954 OUString aElementName = pNames[ i ];
956 // Load binary
957 if( bLoadBinary )
959 SbModule* pMod = pBasicLib->FindModule( aElementName );
960 if( !pMod )
962 pMod = pBasicLib->MakeModule( aElementName, String() );
963 pBasicLib->SetModified( sal_False );
966 OUString aCodeStreamName= aElementName;
967 aCodeStreamName += ".bin";
971 uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement(
972 aCodeStreamName,
973 embed::ElementModes::READ );
974 if ( !xCodeStream.is() )
976 throw uno::RuntimeException();
978 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
979 if ( !pStream || pStream->GetError() )
981 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
982 delete pStream;
983 throw task::ErrorCodeIOException( OUString(), uno::Reference< uno::XInterface >(), nError );
986 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
987 // TODO: Check return value
989 delete pStream;
991 catch(const uno::Exception& )
993 // TODO: error handling
997 // Load source
998 if( bLoadSource || bVerifyPasswordOnly )
1000 // Access encrypted source stream
1001 OUString aSourceStreamName = aElementName;
1002 aSourceStreamName += ".xml";
1006 uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement(
1007 aSourceStreamName,
1008 embed::ElementModes::READ,
1009 pLib->maPassword );
1010 if ( !xSourceStream.is() )
1012 throw uno::RuntimeException();
1014 // if this point is reached then the password is correct
1015 if ( !bVerifyPasswordOnly )
1017 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1018 if ( !xInStream.is() )
1020 throw io::IOException(); // read access denied, seems to be impossible
1022 Reference< XNameContainer > xLib( pLib );
1023 Any aAny = importLibraryElement( xLib,
1024 aElementName, aSourceStreamName,
1025 xInStream );
1026 if( pLib->hasByName( aElementName ) )
1028 if( aAny.hasValue() )
1030 pLib->maNameContainer.replaceByName( aElementName, aAny );
1033 else
1035 pLib->maNameContainer.insertByName( aElementName, aAny );
1039 catch(const uno::Exception& )
1041 bRet = sal_False;
1046 else
1050 OUString aLibDirPath = createAppLibraryFolder( pLib, Name );
1052 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1054 OUString aElementName = pNames[ i ];
1056 INetURLObject aElementInetObj( aLibDirPath );
1057 aElementInetObj.insertName( aElementName, sal_False,
1058 INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
1059 aElementInetObj.setExtension( OUString( "pba" ) );
1060 OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
1062 uno::Reference< embed::XStorage > xElementRootStorage;
1065 xElementRootStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
1066 aElementPath,
1067 embed::ElementModes::READ );
1068 } catch(const uno::Exception& )
1070 // TODO: error handling
1073 if ( xElementRootStorage.is() )
1075 // Load binary
1076 if( bLoadBinary )
1078 SbModule* pMod = pBasicLib->FindModule( aElementName );
1079 if( !pMod )
1081 pMod = pBasicLib->MakeModule( aElementName, String() );
1082 pBasicLib->SetModified( sal_False );
1087 OUString aCodeStreamName( "code.bin" );
1088 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
1089 aCodeStreamName,
1090 embed::ElementModes::READ );
1092 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
1093 if ( !pStream || pStream->GetError() )
1095 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
1096 delete pStream;
1097 throw task::ErrorCodeIOException( OUString(),
1098 uno::Reference< uno::XInterface >(),
1099 nError );
1102 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
1103 // TODO: Check return value
1105 delete pStream;
1107 catch(const uno::Exception& )
1109 // TODO: error handling
1113 // Load source
1114 if( bLoadSource || bVerifyPasswordOnly )
1116 // Access encrypted source stream
1117 OUString aSourceStreamName( "source.xml" );
1120 uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement(
1121 aSourceStreamName,
1122 embed::ElementModes::READ,
1123 pLib->maPassword );
1124 if ( !xSourceStream.is() )
1126 throw uno::RuntimeException();
1128 if ( !bVerifyPasswordOnly )
1130 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1131 if ( !xInStream.is() )
1133 throw io::IOException(); // read access denied, seems to be impossible
1135 Reference< XNameContainer > xLib( pLib );
1136 Any aAny = importLibraryElement( xLib,
1137 aElementName,
1138 aSourceStreamName,
1139 xInStream );
1140 if( pLib->hasByName( aElementName ) )
1142 if( aAny.hasValue() )
1144 pLib->maNameContainer.replaceByName( aElementName, aAny );
1147 else
1149 pLib->maNameContainer.insertByName( aElementName, aAny );
1153 catch (const uno::Exception& )
1155 bRet = sal_False;
1161 catch(const Exception& )
1163 // TODO
1164 //throw e;
1168 return bRet;
1172 void SfxScriptLibraryContainer::onNewRootStorage()
1176 sal_Bool SAL_CALL SfxScriptLibraryContainer:: HasExecutableCode( const OUString& Library )
1177 throw (uno::RuntimeException)
1179 BasicManager* pBasicMgr = getBasicManager();
1180 OSL_ENSURE( pBasicMgr, "we need a basicmanager, really we do" );
1181 if ( pBasicMgr )
1183 return pBasicMgr->HasExeCode( Library ); // need to change this to take name
1185 // default to it has code if we can't decide
1186 return sal_True;
1189 //============================================================================
1190 // Service
1191 void createRegistryInfo_SfxScriptLibraryContainer()
1193 static OAutoRegistration< SfxScriptLibraryContainer > aAutoRegistration;
1196 OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( )
1197 throw (RuntimeException)
1199 return getImplementationName_static();
1202 Sequence< OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( )
1203 throw (RuntimeException)
1205 return getSupportedServiceNames_static();
1208 Sequence< OUString > SfxScriptLibraryContainer::getSupportedServiceNames_static()
1210 Sequence< OUString > aServiceNames( 2 );
1211 aServiceNames[0] = OUString("com.sun.star.script.DocumentScriptLibraryContainer" );
1212 // plus, for compatibility:
1213 aServiceNames[1] = OUString("com.sun.star.script.ScriptLibraryContainer" );
1214 return aServiceNames;
1217 OUString SfxScriptLibraryContainer::getImplementationName_static()
1219 return OUString("com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1222 Reference< XInterface > SAL_CALL SfxScriptLibraryContainer::Create( const Reference< XComponentContext >& )
1223 throw( Exception )
1225 Reference< XInterface > xRet = static_cast< XInterface* >( static_cast< OWeakObject* >(new SfxScriptLibraryContainer()) );
1226 return xRet;
1229 //============================================================================
1230 // Implementation class SfxScriptLibrary
1232 // Ctor
1233 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1234 const Reference< XComponentContext >& xContext,
1235 const Reference< XSimpleFileAccess3 >& xSFI )
1236 : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xContext, xSFI )
1237 , mbLoadedSource( false )
1238 , mbLoadedBinary( false )
1242 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1243 const Reference< XComponentContext >& xContext,
1244 const Reference< XSimpleFileAccess3 >& xSFI,
1245 const OUString& aLibInfoFileURL,
1246 const OUString& aStorageURL,
1247 sal_Bool ReadOnly )
1248 : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xContext, xSFI,
1249 aLibInfoFileURL, aStorageURL, ReadOnly)
1250 , mbLoadedSource( false )
1251 , mbLoadedBinary( false )
1255 // Provide modify state including resources
1256 sal_Bool SfxScriptLibrary::isModified( void )
1258 return implIsModified(); // No resources
1261 void SfxScriptLibrary::storeResources( void )
1263 // No resources
1266 void SfxScriptLibrary::storeResourcesToURL( const OUString& URL,
1267 const Reference< task::XInteractionHandler >& Handler )
1269 (void)URL;
1270 (void)Handler;
1273 void SfxScriptLibrary::storeResourcesAsURL
1274 ( const OUString& URL, const OUString& NewName )
1276 (void)URL;
1277 (void)NewName;
1280 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1281 < ::com::sun::star::embed::XStorage >& xStorage )
1283 // No resources
1284 (void)xStorage;
1287 bool SfxScriptLibrary::containsValidModule( const Any& aElement )
1289 OUString sModuleText;
1290 aElement >>= sModuleText;
1291 return ( !sModuleText.isEmpty() );
1294 bool SAL_CALL SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const
1296 return SfxScriptLibrary::containsValidModule( aElement );
1299 IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1300 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1302 script::ModuleInfo SAL_CALL SfxScriptLibrary::getModuleInfo( const OUString& ModuleName )
1303 throw (NoSuchElementException, WrappedTargetException, RuntimeException)
1305 if ( !hasModuleInfo( ModuleName ) )
1307 throw NoSuchElementException();
1309 return mModuleInfos[ ModuleName ];
1312 sal_Bool SAL_CALL SfxScriptLibrary::hasModuleInfo( const OUString& ModuleName )
1313 throw (RuntimeException)
1315 sal_Bool bRes = sal_False;
1316 ModuleInfoMap::iterator it = mModuleInfos.find( ModuleName );
1318 if ( it != mModuleInfos.end() )
1320 bRes = sal_True;
1322 return bRes;
1325 void SAL_CALL SfxScriptLibrary::insertModuleInfo( const OUString& ModuleName, const script::ModuleInfo& ModuleInfo )
1326 throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
1328 if ( hasModuleInfo( ModuleName ) )
1330 throw ElementExistException();
1332 mModuleInfos[ ModuleName ] = ModuleInfo;
1335 void SAL_CALL SfxScriptLibrary::removeModuleInfo( const OUString& ModuleName )
1336 throw (NoSuchElementException, WrappedTargetException, RuntimeException)
1338 // #FIXME add NoSuchElementException to the spec
1339 if ( !hasModuleInfo( ModuleName ) )
1341 throw NoSuchElementException();
1343 mModuleInfos.erase( mModuleInfos.find( ModuleName ) );
1347 //============================================================================
1349 } // namespace basic
1351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */