Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / basic / source / uno / scriptcont.cxx
blob40bbef1afba10f4c438d51edd67df04e04d1c46f
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, mxMSF, 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, mxMSF, 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(comphelper::getComponentContext(mxMSF));
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( comphelper::getComponentContext(mxMSF) );
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( rtl::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", rtl::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 ::rtl::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 ::rtl::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 ::rtl::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 ::rtl::OUString& aName,
589 const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage,
590 const ::rtl::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<rtl::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 ::rtl::OStringBuffer aMessage;
682 aMessage.append( "invalid library element '" );
683 aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) );
684 aMessage.append( "'." );
685 OSL_FAIL( aMessage.makeStringAndClear().getStr() );
686 #endif
687 continue;
690 OUString aSourceStreamName = aElementName;
691 aSourceStreamName += ".xml";
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() )
701 throw uno::RuntimeException();
703 OUString aMime( "text/xml" );
704 xProps->setPropertyValue( rtl::OUString("MediaType"), uno::makeAny( aMime ) );
706 // Set encryption key
707 setStreamKey( xSourceStream, pLib->maPassword );
709 Reference< XOutputStream > xOutput = xSourceStream->getOutputStream();
710 Reference< XNameContainer > xLib( pLib );
711 writeLibraryElement( xLib, aElementName, xOutput );
713 catch(const uno::Exception& )
715 OSL_FAIL( "Problem on storing of password library!\n" );
716 // TODO: error handling
719 else // !mbPasswordVerified
721 // TODO
722 // What to do if not verified?! In any case it's already loaded here
727 // Application libraries have only to be saved if the password
728 // is verified because otherwise they can't be modified
729 else if( pLib->mbPasswordVerified || bExport )
733 Reference< XSimpleFileAccess3 > xSFI = mxSFI;
734 if( xToUseSFI.is() )
736 xSFI = xToUseSFI;
738 OUString aLibDirPath;
739 if( bExport )
741 INetURLObject aInetObj( aTargetURL );
742 aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True,
743 INetURLObject::ENCODE_ALL );
744 aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
746 if( !xSFI->isFolder( aLibDirPath ) )
748 xSFI->createFolder( aLibDirPath );
751 else
753 aLibDirPath = createAppLibraryFolder( pLib, aName );
756 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
758 OUString aElementName = pNames[ i ];
760 INetURLObject aElementInetObj( aLibDirPath );
761 aElementInetObj.insertName( aElementName, sal_False,
762 INetURLObject::LAST_SEGMENT, sal_True,
763 INetURLObject::ENCODE_ALL );
764 aElementInetObj.setExtension( OUString( "pba" ) );
765 OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
767 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
769 #if OSL_DEBUG_LEVEL > 0
770 ::rtl::OStringBuffer aMessage;
771 aMessage.append( "invalid library element '" );
772 aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) );
773 aMessage.append( "'." );
774 OSL_FAIL( aMessage.makeStringAndClear().getStr() );
775 #endif
776 continue;
781 uno::Reference< embed::XStorage > xElementRootStorage =
782 ::comphelper::OStorageHelper::GetStorageFromURL(
783 aElementPath,
784 embed::ElementModes::READWRITE );
785 if ( !xElementRootStorage.is() )
787 throw uno::RuntimeException();
789 // Write binary image stream
790 SbModule* pMod = pBasicLib->FindModule( aElementName );
791 if( pMod )
793 OUString aCodeStreamName( "code.bin" );
795 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
796 aCodeStreamName,
797 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
799 SvMemoryStream aMemStream;
800 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
802 sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
803 Sequence< sal_Int8 > aBinSeq( nSize );
804 sal_Int8* pData = aBinSeq.getArray();
805 memcpy( pData, aMemStream.GetData(), nSize );
807 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
808 if ( xOut.is() )
810 xOut->writeBytes( aBinSeq );
811 xOut->closeOutput();
815 // Write encrypted source stream
816 OUString aSourceStreamName( "source.xml" );
818 uno::Reference< io::XStream > xSourceStream;
821 xSourceStream = xElementRootStorage->openStreamElement(
822 aSourceStreamName,
823 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
825 // #87671 Allow encryption
826 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY );
827 OSL_ENSURE( xEncr.is(),
828 "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
829 if ( !xEncr.is() )
831 throw uno::RuntimeException();
833 xEncr->setEncryptionPassword( pLib->maPassword );
835 catch(const ::com::sun::star::packages::WrongPasswordException& )
837 xSourceStream = xElementRootStorage->openEncryptedStreamElement(
838 aSourceStreamName,
839 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
840 pLib->maPassword );
843 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
844 if ( !xProps.is() )
846 throw uno::RuntimeException();
848 OUString aMime( "text/xml" );
849 xProps->setPropertyValue( rtl::OUString("MediaType"), uno::makeAny( aMime ) );
851 Reference< XOutputStream > xOut = xSourceStream->getOutputStream();
852 Reference< XNameContainer > xLib( pLib );
853 writeLibraryElement( xLib, aElementName, xOut );
854 // i50568: sax writer already closes stream
855 // xOut->closeOutput();
857 uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY );
858 OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" );
859 if ( !xTransact.is() )
861 throw uno::RuntimeException();
864 xTransact->commit();
866 catch(const uno::Exception& )
868 // TODO: handle error
873 catch(const Exception& )
877 return sal_True;
880 sal_Bool SfxScriptLibraryContainer::implLoadPasswordLibrary
881 ( SfxLibrary* pLib, const OUString& Name, sal_Bool bVerifyPasswordOnly )
882 throw(WrappedTargetException, RuntimeException)
884 sal_Bool bRet = sal_True;
886 sal_Bool bLink = pLib->mbLink;
887 sal_Bool bStorage = mxStorage.is() && !bLink;
889 // Already loaded? Then only verifiedPassword can change something
890 SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib );
891 if( pScriptLib->mbLoaded )
893 if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly &&
894 (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) )
896 return sal_False;
900 StarBASIC* pBasicLib = NULL;
901 sal_Bool bLoadBinary = sal_False;
902 if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified )
904 BasicManager* pBasicMgr = getBasicManager();
905 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
906 sal_Bool bLoaded = pScriptLib->mbLoaded;
907 pScriptLib->mbLoaded = sal_True; // Necessary to get lib
908 pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : NULL;
909 pScriptLib->mbLoaded = bLoaded; // Restore flag
910 if( !pBasicLib )
912 return sal_False;
914 bLoadBinary = sal_True;
915 pScriptLib->mbLoadedBinary = true;
918 sal_Bool bLoadSource = sal_False;
919 if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly )
921 bLoadSource = sal_True;
922 pScriptLib->mbLoadedSource = true;
925 Sequence< OUString > aElementNames = pLib->getElementNames();
926 sal_Int32 nNameCount = aElementNames.getLength();
927 const OUString* pNames = aElementNames.getConstArray();
929 if( bStorage )
931 uno::Reference< embed::XStorage > xLibrariesStor;
932 uno::Reference< embed::XStorage > xLibraryStor;
933 if( bStorage )
935 try {
936 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
937 if ( !xLibrariesStor.is() )
939 throw uno::RuntimeException();
941 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
942 if ( !xLibraryStor.is() )
944 throw uno::RuntimeException();
947 catch(const uno::Exception& )
949 OSL_FAIL( "### couldn't open sub storage for library\n" );
950 return sal_False;
954 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
956 OUString aElementName = pNames[ i ];
958 // Load binary
959 if( bLoadBinary )
961 SbModule* pMod = pBasicLib->FindModule( aElementName );
962 if( !pMod )
964 pMod = pBasicLib->MakeModule( aElementName, String() );
965 pBasicLib->SetModified( sal_False );
968 OUString aCodeStreamName= aElementName;
969 aCodeStreamName += ".bin";
973 uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement(
974 aCodeStreamName,
975 embed::ElementModes::READ );
976 if ( !xCodeStream.is() )
978 throw uno::RuntimeException();
980 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
981 if ( !pStream || pStream->GetError() )
983 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
984 delete pStream;
985 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), nError );
988 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
989 // TODO: Check return value
991 delete pStream;
993 catch(const uno::Exception& )
995 // TODO: error handling
999 // Load source
1000 if( bLoadSource || bVerifyPasswordOnly )
1002 // Access encrypted source stream
1003 OUString aSourceStreamName = aElementName;
1004 aSourceStreamName += ".xml";
1008 uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement(
1009 aSourceStreamName,
1010 embed::ElementModes::READ,
1011 pLib->maPassword );
1012 if ( !xSourceStream.is() )
1014 throw uno::RuntimeException();
1016 // if this point is reached then the password is correct
1017 if ( !bVerifyPasswordOnly )
1019 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1020 if ( !xInStream.is() )
1022 throw io::IOException(); // read access denied, seems to be impossible
1024 Reference< XNameContainer > xLib( pLib );
1025 Any aAny = importLibraryElement( xLib,
1026 aElementName, aSourceStreamName,
1027 xInStream );
1028 if( pLib->hasByName( aElementName ) )
1030 if( aAny.hasValue() )
1032 pLib->maNameContainer.replaceByName( aElementName, aAny );
1035 else
1037 pLib->maNameContainer.insertByName( aElementName, aAny );
1041 catch(const uno::Exception& )
1043 bRet = sal_False;
1048 else
1052 OUString aLibDirPath = createAppLibraryFolder( pLib, Name );
1054 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1056 OUString aElementName = pNames[ i ];
1058 INetURLObject aElementInetObj( aLibDirPath );
1059 aElementInetObj.insertName( aElementName, sal_False,
1060 INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
1061 aElementInetObj.setExtension( OUString( "pba" ) );
1062 OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
1064 uno::Reference< embed::XStorage > xElementRootStorage;
1067 xElementRootStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
1068 aElementPath,
1069 embed::ElementModes::READ );
1070 } catch(const uno::Exception& )
1072 // TODO: error handling
1075 if ( xElementRootStorage.is() )
1077 // Load binary
1078 if( bLoadBinary )
1080 SbModule* pMod = pBasicLib->FindModule( aElementName );
1081 if( !pMod )
1083 pMod = pBasicLib->MakeModule( aElementName, String() );
1084 pBasicLib->SetModified( sal_False );
1089 OUString aCodeStreamName( "code.bin" );
1090 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
1091 aCodeStreamName,
1092 embed::ElementModes::READ );
1094 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
1095 if ( !pStream || pStream->GetError() )
1097 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
1098 delete pStream;
1099 throw task::ErrorCodeIOException( ::rtl::OUString(),
1100 uno::Reference< uno::XInterface >(),
1101 nError );
1104 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
1105 // TODO: Check return value
1107 delete pStream;
1109 catch(const uno::Exception& )
1111 // TODO: error handling
1115 // Load source
1116 if( bLoadSource || bVerifyPasswordOnly )
1118 // Access encrypted source stream
1119 OUString aSourceStreamName( "source.xml" );
1122 uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement(
1123 aSourceStreamName,
1124 embed::ElementModes::READ,
1125 pLib->maPassword );
1126 if ( !xSourceStream.is() )
1128 throw uno::RuntimeException();
1130 if ( !bVerifyPasswordOnly )
1132 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1133 if ( !xInStream.is() )
1135 throw io::IOException(); // read access denied, seems to be impossible
1137 Reference< XNameContainer > xLib( pLib );
1138 Any aAny = importLibraryElement( xLib,
1139 aElementName,
1140 aSourceStreamName,
1141 xInStream );
1142 if( pLib->hasByName( aElementName ) )
1144 if( aAny.hasValue() )
1146 pLib->maNameContainer.replaceByName( aElementName, aAny );
1149 else
1151 pLib->maNameContainer.insertByName( aElementName, aAny );
1155 catch (const uno::Exception& )
1157 bRet = sal_False;
1163 catch(const Exception& )
1165 // TODO
1166 //throw e;
1170 return bRet;
1174 void SfxScriptLibraryContainer::onNewRootStorage()
1178 sal_Bool SAL_CALL SfxScriptLibraryContainer:: HasExecutableCode( const ::rtl::OUString& Library )
1179 throw (uno::RuntimeException)
1181 BasicManager* pBasicMgr = getBasicManager();
1182 OSL_ENSURE( pBasicMgr, "we need a basicmanager, really we do" );
1183 if ( pBasicMgr )
1185 return pBasicMgr->HasExeCode( Library ); // need to change this to take name
1187 // default to it has code if we can't decide
1188 return sal_True;
1191 //============================================================================
1192 // Service
1193 void createRegistryInfo_SfxScriptLibraryContainer()
1195 static OAutoRegistration< SfxScriptLibraryContainer > aAutoRegistration;
1198 OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( )
1199 throw (RuntimeException)
1201 return getImplementationName_static();
1204 Sequence< OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( )
1205 throw (RuntimeException)
1207 return getSupportedServiceNames_static();
1210 Sequence< OUString > SfxScriptLibraryContainer::getSupportedServiceNames_static()
1212 Sequence< OUString > aServiceNames( 2 );
1213 aServiceNames[0] = OUString("com.sun.star.script.DocumentScriptLibraryContainer" );
1214 // plus, for compatibility:
1215 aServiceNames[1] = OUString("com.sun.star.script.ScriptLibraryContainer" );
1216 return aServiceNames;
1219 OUString SfxScriptLibraryContainer::getImplementationName_static()
1221 return OUString("com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1224 Reference< XInterface > SAL_CALL SfxScriptLibraryContainer::Create( const Reference< XComponentContext >& )
1225 throw( Exception )
1227 Reference< XInterface > xRet = static_cast< XInterface* >( static_cast< OWeakObject* >(new SfxScriptLibraryContainer()) );
1228 return xRet;
1231 //============================================================================
1232 // Implementation class SfxScriptLibrary
1234 // Ctor
1235 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1236 const Reference< XMultiServiceFactory >& xMSF,
1237 const Reference< XSimpleFileAccess3 >& xSFI )
1238 : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI )
1239 , mbLoadedSource( false )
1240 , mbLoadedBinary( false )
1244 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1245 const Reference< XMultiServiceFactory >& xMSF,
1246 const Reference< XSimpleFileAccess3 >& xSFI,
1247 const OUString& aLibInfoFileURL,
1248 const OUString& aStorageURL,
1249 sal_Bool ReadOnly )
1250 : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI,
1251 aLibInfoFileURL, aStorageURL, ReadOnly)
1252 , mbLoadedSource( false )
1253 , mbLoadedBinary( false )
1257 // Provide modify state including resources
1258 sal_Bool SfxScriptLibrary::isModified( void )
1260 return implIsModified(); // No resources
1263 void SfxScriptLibrary::storeResources( void )
1265 // No resources
1268 void SfxScriptLibrary::storeResourcesToURL( const ::rtl::OUString& URL,
1269 const Reference< task::XInteractionHandler >& Handler )
1271 (void)URL;
1272 (void)Handler;
1275 void SfxScriptLibrary::storeResourcesAsURL
1276 ( const ::rtl::OUString& URL, const ::rtl::OUString& NewName )
1278 (void)URL;
1279 (void)NewName;
1282 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1283 < ::com::sun::star::embed::XStorage >& xStorage )
1285 // No resources
1286 (void)xStorage;
1289 bool SfxScriptLibrary::containsValidModule( const Any& aElement )
1291 OUString sModuleText;
1292 aElement >>= sModuleText;
1293 return ( !sModuleText.isEmpty() );
1296 bool SAL_CALL SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const
1298 return SfxScriptLibrary::containsValidModule( aElement );
1301 IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1302 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1304 script::ModuleInfo SAL_CALL SfxScriptLibrary::getModuleInfo( const OUString& ModuleName )
1305 throw (NoSuchElementException, WrappedTargetException, RuntimeException)
1307 if ( !hasModuleInfo( ModuleName ) )
1309 throw NoSuchElementException();
1311 return mModuleInfos[ ModuleName ];
1314 sal_Bool SAL_CALL SfxScriptLibrary::hasModuleInfo( const OUString& ModuleName )
1315 throw (RuntimeException)
1317 sal_Bool bRes = sal_False;
1318 ModuleInfoMap::iterator it = mModuleInfos.find( ModuleName );
1320 if ( it != mModuleInfos.end() )
1322 bRes = sal_True;
1324 return bRes;
1327 void SAL_CALL SfxScriptLibrary::insertModuleInfo( const OUString& ModuleName, const script::ModuleInfo& ModuleInfo )
1328 throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
1330 if ( hasModuleInfo( ModuleName ) )
1332 throw ElementExistException();
1334 mModuleInfos[ ModuleName ] = ModuleInfo;
1337 void SAL_CALL SfxScriptLibrary::removeModuleInfo( const OUString& ModuleName )
1338 throw (NoSuchElementException, WrappedTargetException, RuntimeException)
1340 // #FIXME add NoSuchElementException to the spec
1341 if ( !hasModuleInfo( ModuleName ) )
1343 throw NoSuchElementException();
1345 mModuleInfos.erase( mModuleInfos.find( ModuleName ) );
1349 //============================================================================
1351 } // namespace basic
1353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */