update credits
[LibreOffice.git] / basic / source / uno / scriptcont.cxx
blobbbf1fa6b211778006dc7442d1fa85587cef50a61
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 <filefmt.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/processfactory.hxx>
37 #include <comphelper/storagehelper.hxx>
38 #include <unotools/streamwrap.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <osl/mutex.hxx>
41 #include <osl/thread.h>
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 #include <boost/scoped_ptr.hpp>
63 namespace basic
66 using namespace com::sun::star::document;
67 using namespace com::sun::star::container;
68 using namespace com::sun::star::io;
69 using namespace com::sun::star::uno;
70 using namespace com::sun::star::ucb;
71 using namespace com::sun::star::lang;
72 using namespace com::sun::star::script;
73 using namespace com::sun::star::xml::sax;
74 using namespace com::sun::star;
75 using namespace cppu;
76 using namespace osl;
79 // Implementation class SfxScriptLibraryContainer
81 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getInfoFileName() const { return "script"; }
82 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; }
83 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; }
84 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; }
86 // OldBasicPassword interface
87 void SfxScriptLibraryContainer::setLibraryPassword( const OUString& rLibraryName, const OUString& rPassword )
89 try
91 SfxLibrary* pImplLib = getImplLib( rLibraryName );
92 if( !rPassword.isEmpty() )
94 pImplLib->mbDoc50Password = true;
95 pImplLib->mbPasswordProtected = true;
96 pImplLib->maPassword = rPassword;
99 catch(const NoSuchElementException& ) {}
102 OUString SfxScriptLibraryContainer::getLibraryPassword( const OUString& rLibraryName )
104 SfxLibrary* pImplLib = getImplLib( rLibraryName );
105 OUString aPassword;
106 if( pImplLib->mbPasswordVerified )
108 aPassword = pImplLib->maPassword;
110 return aPassword;
113 void SfxScriptLibraryContainer::clearLibraryPassword( const OUString& rLibraryName )
117 SfxLibrary* pImplLib = getImplLib( rLibraryName );
118 pImplLib->mbDoc50Password = false;
119 pImplLib->mbPasswordProtected = false;
120 pImplLib->maPassword.clear();
122 catch(const NoSuchElementException& ) {}
125 bool SfxScriptLibraryContainer::hasLibraryPassword( const OUString& rLibraryName )
127 SfxLibrary* pImplLib = getImplLib( rLibraryName );
128 return pImplLib->mbPasswordProtected;
131 // Ctor for service
132 SfxScriptLibraryContainer::SfxScriptLibraryContainer()
133 :maScriptLanguage( "StarBasic" )
135 // all initialisation has to be done
136 // by calling XInitialization::initialize
139 SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference< embed::XStorage >& xStorage )
140 :maScriptLanguage( "StarBasic" )
142 init( OUString(), xStorage );
145 // Methods to get library instances of the correct type
146 SfxLibrary* SfxScriptLibraryContainer::implCreateLibrary( const OUString& aName )
148 (void)aName; // Only needed for SfxDialogLibrary
149 SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxContext, mxSFI );
150 return pRet;
153 SfxLibrary* SfxScriptLibraryContainer::implCreateLibraryLink( const OUString& aName,
154 const OUString& aLibInfoFileURL,
155 const OUString& StorageURL,
156 bool ReadOnly )
158 (void)aName; // Only needed for SfxDialogLibrary
159 SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxContext, mxSFI,
160 aLibInfoFileURL, StorageURL, ReadOnly );
161 return pRet;
164 Any SAL_CALL SfxScriptLibraryContainer::createEmptyLibraryElement()
166 OUString aMod;
167 Any aRetAny;
168 aRetAny <<= aMod;
169 return aRetAny;
172 bool SAL_CALL SfxScriptLibraryContainer::isLibraryElementValid(const Any& rElement) const
174 return SfxScriptLibrary::containsValidModule(rElement);
177 void SAL_CALL SfxScriptLibraryContainer::writeLibraryElement( const Reference < XNameContainer >& xLib,
178 const OUString& aElementName,
179 const Reference< XOutputStream >& xOutput)
180 throw(Exception)
182 // Create sax writer
183 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
185 Reference< XTruncate > xTruncate( xOutput, UNO_QUERY );
186 OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" );
187 if ( xTruncate.is() )
189 xTruncate->truncate();
191 xWriter->setOutputStream( xOutput );
193 xmlscript::ModuleDescriptor aMod;
194 aMod.aName = aElementName;
195 aMod.aLanguage = maScriptLanguage;
196 Any aElement = xLib->getByName( aElementName );
197 aElement >>= aMod.aCode;
199 Reference< script::vba::XVBAModuleInfo > xModInfo( xLib, UNO_QUERY );
200 if( xModInfo.is() && xModInfo->hasModuleInfo( aElementName ) )
202 script::ModuleInfo aModInfo = xModInfo->getModuleInfo( aElementName );
203 switch( aModInfo.ModuleType )
205 case ModuleType::NORMAL:
206 aMod.aModuleType = "normal";
207 break;
208 case ModuleType::CLASS:
209 aMod.aModuleType ="class";
210 break;
211 case ModuleType::FORM:
212 aMod.aModuleType = "form";
213 break;
214 case ModuleType::DOCUMENT:
215 aMod.aModuleType = "document";
216 break;
217 case ModuleType::UNKNOWN:
218 // nothing
219 break;
223 xmlscript::exportScriptModule( xWriter, aMod );
227 Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement
228 ( const Reference < XNameContainer >& xLib,
229 const OUString& aElementName, const OUString& aFile,
230 const uno::Reference< io::XInputStream >& xInStream )
232 Any aRetAny;
234 Reference< XParser > xParser = xml::sax::Parser::create( mxContext );
236 // Read from storage?
237 bool bStorage = xInStream.is();
238 Reference< XInputStream > xInput;
240 if( bStorage )
242 xInput = xInStream;
244 else
248 xInput = mxSFI->openFileRead( aFile );
250 catch(const Exception& )
251 //catch( Exception& e )
253 // TODO:
254 //throw WrappedTargetException( e );
258 if( !xInput.is() )
259 return aRetAny;
261 InputSource source;
262 source.aInputStream = xInput;
263 source.sSystemId = aFile;
265 // start parsing
266 xmlscript::ModuleDescriptor aMod;
270 xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) );
271 xParser->parseStream( source );
273 catch(const Exception& )
275 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile );
276 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
279 aRetAny <<= aMod.aCode;
281 // TODO: Check language
282 // aMod.aLanguage
283 // aMod.aName ignored
284 if( !aMod.aModuleType.isEmpty() )
286 /* If in VBA compatibility mode, force creation of the VBA Globals
287 object. Each application will create an instance of its own
288 implementation and store it in its Basic manager. Implementations
289 will do all necessary additional initialization, such as
290 registering the global "This***Doc" UNO constant, starting the
291 document events processor etc.
293 if( getVBACompatibilityMode() ) try
295 Reference< frame::XModel > xModel( mxOwnerDocument ); // weak-ref -> ref
296 Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
297 xFactory->createInstance("ooo.vba.VBAGlobals");
299 catch(const Exception& )
303 script::ModuleInfo aModInfo;
304 aModInfo.ModuleType = ModuleType::UNKNOWN;
305 if( aMod.aModuleType == "normal" )
307 aModInfo.ModuleType = ModuleType::NORMAL;
309 else if( aMod.aModuleType == "class" )
311 aModInfo.ModuleType = ModuleType::CLASS;
313 else if( aMod.aModuleType == "form" )
315 aModInfo.ModuleType = ModuleType::FORM;
316 aModInfo.ModuleObject = mxOwnerDocument;
318 else if( aMod.aModuleType == "document" )
320 aModInfo.ModuleType = ModuleType::DOCUMENT;
322 // #163691# use the same codename access instance for all document modules
323 if( !mxCodeNameAccess.is() ) try
325 Reference<frame::XModel > xModel( mxOwnerDocument );
326 Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY_THROW );
327 mxCodeNameAccess.set( xSF->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), UNO_QUERY );
329 catch(const Exception& ) {}
331 if( mxCodeNameAccess.is() )
335 aModInfo.ModuleObject.set( mxCodeNameAccess->getByName( aElementName), uno::UNO_QUERY );
337 catch(const uno::Exception&)
339 OSL_TRACE("Failed to get documument object for %s", OUStringToOString( aElementName, RTL_TEXTENCODING_UTF8 ).getStr() );
344 Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
345 if( xVBAModuleInfo.is() )
347 if( xVBAModuleInfo->hasModuleInfo( aElementName ) )
349 xVBAModuleInfo->removeModuleInfo( aElementName );
351 xVBAModuleInfo->insertModuleInfo( aElementName, aModInfo );
355 return aRetAny;
358 SfxLibraryContainer* SfxScriptLibraryContainer::createInstanceImpl()
360 return new SfxScriptLibraryContainer();
363 void SAL_CALL SfxScriptLibraryContainer::importFromOldStorage( const OUString& aFile )
365 // TODO: move loading from old storage to binary filters?
366 tools::SvRef<SotStorage> xStorage = new SotStorage( false, aFile );
367 if( xStorage.Is() && xStorage->GetError() == ERRCODE_NONE )
369 BasicManager* pBasicManager = new BasicManager( *(SotStorage*)xStorage, aFile );
371 // Set info
372 LibraryContainerInfo aInfo( this, NULL, static_cast< OldBasicPassword* >( this ) );
373 pBasicManager->SetLibraryContainerInfo( aInfo );
375 // Now the libraries should be copied to this SfxScriptLibraryContainer
376 BasicManager::LegacyDeleteBasicManager( pBasicManager );
381 // Storing with password encryption
383 // Methods XLibraryContainerPassword
384 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString& Name )
385 throw (NoSuchElementException, RuntimeException, std::exception)
387 LibraryContainerMethodGuard aGuard( *this );
388 SfxLibrary* pImplLib = getImplLib( Name );
389 bool bRet = pImplLib->mbPasswordProtected;
390 return bRet;
393 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString& Name )
394 throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
396 LibraryContainerMethodGuard aGuard( *this );
397 SfxLibrary* pImplLib = getImplLib( Name );
398 if( !pImplLib->mbPasswordProtected )
400 throw IllegalArgumentException();
402 bool bRet = pImplLib->mbPasswordVerified;
403 return bRet;
406 sal_Bool SAL_CALL SfxScriptLibraryContainer::verifyLibraryPassword
407 ( const OUString& Name, const OUString& Password )
408 throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
410 LibraryContainerMethodGuard aGuard( *this );
411 SfxLibrary* pImplLib = getImplLib( Name );
412 if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified )
414 throw IllegalArgumentException();
416 // Test password
417 bool bSuccess = false;
418 if( pImplLib->mbDoc50Password )
420 bSuccess = ( Password == pImplLib->maPassword );
421 if( bSuccess )
423 pImplLib->mbPasswordVerified = true;
426 else
428 pImplLib->maPassword = Password;
429 bSuccess = implLoadPasswordLibrary( pImplLib, Name, true );
430 if( bSuccess )
432 // The library gets modified by verifying the password, because other-
433 // wise for saving the storage would be copied and that doesn't work
434 // with mtg's storages when the password is verified
435 pImplLib->implSetModified( true );
436 pImplLib->mbPasswordVerified = true;
438 // Reload library to get source
439 if( pImplLib->mbLoaded )
441 implLoadPasswordLibrary( pImplLib, Name );
445 return bSuccess;
448 void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name,
449 const OUString& OldPassword,
450 const OUString& NewPassword )
451 throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
453 LibraryContainerMethodGuard aGuard( *this );
454 SfxLibrary* pImplLib = getImplLib( Name );
455 if( OldPassword == NewPassword )
457 return;
459 bool bOldPassword = !OldPassword.isEmpty();
460 bool bNewPassword = !NewPassword.isEmpty();
461 bool bStorage = mxStorage.is() && !pImplLib->mbLink;
463 if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) )
465 throw IllegalArgumentException();
467 // Library must be loaded
468 loadLibrary( Name );
470 bool bKillCryptedFiles = false;
471 bool bKillUncryptedFiles = false;
473 // Remove or change password?
474 if( bOldPassword )
476 if( isLibraryPasswordVerified( Name ) )
478 if( pImplLib->maPassword != OldPassword )
480 throw IllegalArgumentException();
483 else
485 if( !verifyLibraryPassword( Name, OldPassword ) )
487 throw IllegalArgumentException();
489 // Reload library to get source
490 // Should be done in verifyLibraryPassword loadLibrary( Name );
493 if( !bNewPassword )
495 pImplLib->mbPasswordProtected = false;
496 pImplLib->mbPasswordVerified = false;
497 pImplLib->maPassword.clear();
499 maModifiable.setModified( true );
500 pImplLib->implSetModified( true );
502 if( !bStorage && !pImplLib->mbDoc50Password )
504 // Store application basic uncrypted
505 uno::Reference< embed::XStorage > xStorage;
506 storeLibraries_Impl( xStorage, false );
507 bKillCryptedFiles = true;
512 // Set new password?
513 if( bNewPassword )
515 pImplLib->mbPasswordProtected = true;
516 pImplLib->mbPasswordVerified = true;
517 pImplLib->maPassword = NewPassword;
519 maModifiable.setModified( true );
520 pImplLib->implSetModified( true );
522 if( !bStorage && !pImplLib->mbDoc50Password )
524 // Store application basic crypted
525 uno::Reference< embed::XStorage > xStorage;
526 storeLibraries_Impl( xStorage, false );
527 bKillUncryptedFiles = true;
531 if( bKillCryptedFiles || bKillUncryptedFiles )
533 Sequence< OUString > aElementNames = pImplLib->getElementNames();
534 sal_Int32 nNameCount = aElementNames.getLength();
535 const OUString* pNames = aElementNames.getConstArray();
536 OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name );
539 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
541 OUString aElementName = pNames[ i ];
543 INetURLObject aElementInetObj( aLibDirPath );
544 aElementInetObj.insertName( aElementName, false,
545 INetURLObject::LAST_SEGMENT, true,
546 INetURLObject::ENCODE_ALL );
547 if( bKillUncryptedFiles )
549 aElementInetObj.setExtension( maLibElementFileExtension );
551 else
553 aElementInetObj.setExtension( OUString( "pba" ) );
555 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) );
557 if( mxSFI->exists( aElementPath ) )
559 mxSFI->kill( aElementPath );
563 catch(const Exception& ) {}
568 void setStreamKey( uno::Reference< io::XStream > xStream, const OUString& aPass )
570 uno::Reference< embed::XEncryptionProtectedSource > xEncrStream( xStream, uno::UNO_QUERY );
571 if ( xEncrStream.is() )
573 xEncrStream->setEncryptionPassword( aPass );
578 // Impl methods
579 bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib,
580 const OUString& aName,
581 const uno::Reference< embed::XStorage >& xStorage,
582 const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
584 OUString aDummyLocation;
585 Reference< XSimpleFileAccess3 > xDummySFA;
586 return implStorePasswordLibrary( pLib, aName, xStorage, aDummyLocation, xDummySFA, xHandler );
589 bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const OUString& aName,
590 const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage,
591 const OUString& aTargetURL,
592 const Reference< XSimpleFileAccess3 >& rToUseSFI,
593 const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
595 bool bExport = !aTargetURL.isEmpty();
597 BasicManager* pBasicMgr = getBasicManager();
598 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" );
599 if ( !pBasicMgr )
601 return false;
603 // Only need to handle the export case here,
604 // save/saveas etc are handled in sfxbasemodel::storeSelf &
605 // sfxbasemodel::impl_store
606 uno::Sequence<OUString> aNames;
607 if ( bExport && pBasicMgr->LegacyPsswdBinaryLimitExceeded(aNames) )
609 if ( xHandler.is() )
611 ModuleSizeExceeded* pReq = new ModuleSizeExceeded( aNames );
612 uno::Reference< task::XInteractionRequest > xReq( pReq );
613 xHandler->handle( xReq );
614 if ( pReq->isAbort() )
616 throw util::VetoException();
621 StarBASIC* pBasicLib = pBasicMgr->GetLib( aName );
622 if( !pBasicLib )
624 return false;
626 Sequence< OUString > aElementNames = pLib->getElementNames();
627 sal_Int32 nNameCount = aElementNames.getLength();
628 const OUString* pNames = aElementNames.getConstArray();
630 bool bLink = pLib->mbLink;
631 bool bStorage = xStorage.is() && !bLink;
632 if( bStorage )
634 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
636 OUString aElementName = pNames[ i ];
638 // Write binary image stream
639 SbModule* pMod = pBasicLib->FindModule( aElementName );
640 if( pMod )
642 OUString aCodeStreamName = aElementName;
643 aCodeStreamName += ".bin";
647 uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement(
648 aCodeStreamName,
649 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
651 if ( !xCodeStream.is() )
653 throw uno::RuntimeException();
655 SvMemoryStream aMemStream;
656 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream, B_CURVERSION );
658 sal_Size nSize = aMemStream.Tell();
659 Sequence< sal_Int8 > aBinSeq( nSize );
660 sal_Int8* pData = aBinSeq.getArray();
661 memcpy( pData, aMemStream.GetData(), nSize );
663 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
664 if ( !xOut.is() )
666 throw io::IOException(); // access denied because the stream is readonly
668 xOut->writeBytes( aBinSeq );
669 xOut->closeOutput();
671 catch(const uno::Exception& )
673 // TODO: handle error
677 if( pLib->mbPasswordVerified || pLib->mbDoc50Password )
679 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
681 #if OSL_DEBUG_LEVEL > 0
682 OString aMessage = "invalid library element '" +
683 OUStringToOString( aElementName, osl_getThreadTextEncoding() ) +
684 "'.";
685 OSL_FAIL( aMessage.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("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( rToUseSFI.is() )
736 xSFI = rToUseSFI;
738 OUString aLibDirPath;
739 if( bExport )
741 INetURLObject aInetObj( aTargetURL );
742 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, 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, false,
762 INetURLObject::LAST_SEGMENT, 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 OString aMessage = "invalid library element '" +
771 OUStringToOString( aElementName, osl_getThreadTextEncoding() ) +
772 "'.";
773 OSL_FAIL( aMessage.getStr());
774 #endif
775 continue;
780 uno::Reference< embed::XStorage > xElementRootStorage =
781 ::comphelper::OStorageHelper::GetStorageFromURL(
782 aElementPath,
783 embed::ElementModes::READWRITE );
784 if ( !xElementRootStorage.is() )
786 throw uno::RuntimeException();
788 // Write binary image stream
789 SbModule* pMod = pBasicLib->FindModule( aElementName );
790 if( pMod )
792 OUString aCodeStreamName( "code.bin" );
794 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
795 aCodeStreamName,
796 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
798 SvMemoryStream aMemStream;
799 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream, B_CURVERSION );
801 sal_Size nSize = aMemStream.Tell();
802 Sequence< sal_Int8 > aBinSeq( nSize );
803 sal_Int8* pData = aBinSeq.getArray();
804 memcpy( pData, aMemStream.GetData(), nSize );
806 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
807 if ( xOut.is() )
809 xOut->writeBytes( aBinSeq );
810 xOut->closeOutput();
814 // Write encrypted source stream
815 OUString aSourceStreamName( "source.xml" );
817 uno::Reference< io::XStream > xSourceStream;
820 xSourceStream = xElementRootStorage->openStreamElement(
821 aSourceStreamName,
822 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
824 // #87671 Allow encryption
825 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY );
826 OSL_ENSURE( xEncr.is(),
827 "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
828 if ( !xEncr.is() )
830 throw uno::RuntimeException();
832 xEncr->setEncryptionPassword( pLib->maPassword );
834 catch(const ::com::sun::star::packages::WrongPasswordException& )
836 xSourceStream = xElementRootStorage->openEncryptedStreamElement(
837 aSourceStreamName,
838 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
839 pLib->maPassword );
842 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
843 if ( !xProps.is() )
845 throw uno::RuntimeException();
847 OUString aMime( "text/xml" );
848 xProps->setPropertyValue("MediaType", uno::makeAny( aMime ) );
850 Reference< XOutputStream > xOut = xSourceStream->getOutputStream();
851 Reference< XNameContainer > xLib( pLib );
852 writeLibraryElement( xLib, aElementName, xOut );
853 // i50568: sax writer already closes stream
854 // xOut->closeOutput();
856 uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY );
857 OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" );
858 if ( !xTransact.is() )
860 throw uno::RuntimeException();
863 xTransact->commit();
865 catch(const uno::Exception& )
867 // TODO: handle error
872 catch(const Exception& )
876 return true;
879 bool SfxScriptLibraryContainer::implLoadPasswordLibrary
880 ( SfxLibrary* pLib, const OUString& Name, bool bVerifyPasswordOnly )
881 throw(WrappedTargetException, RuntimeException)
883 bool bRet = true;
885 bool bLink = pLib->mbLink;
886 bool bStorage = mxStorage.is() && !bLink;
888 // Already loaded? Then only verifiedPassword can change something
889 SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib );
890 if( pScriptLib->mbLoaded )
892 if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly &&
893 (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) )
895 return false;
899 StarBASIC* pBasicLib = NULL;
900 bool bLoadBinary = false;
901 if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified )
903 BasicManager* pBasicMgr = getBasicManager();
904 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
905 bool bLoaded = pScriptLib->mbLoaded;
906 pScriptLib->mbLoaded = true; // Necessary to get lib
907 pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : NULL;
908 pScriptLib->mbLoaded = bLoaded; // Restore flag
909 if( !pBasicLib )
911 return false;
913 bLoadBinary = true;
914 pScriptLib->mbLoadedBinary = true;
917 bool bLoadSource = false;
918 if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly )
920 bLoadSource = true;
921 pScriptLib->mbLoadedSource = true;
924 Sequence< OUString > aElementNames = pLib->getElementNames();
925 sal_Int32 nNameCount = aElementNames.getLength();
926 const OUString* pNames = aElementNames.getConstArray();
928 if( bStorage )
930 uno::Reference< embed::XStorage > xLibrariesStor;
931 uno::Reference< embed::XStorage > xLibraryStor;
932 if( bStorage )
934 try {
935 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
936 if ( !xLibrariesStor.is() )
938 throw uno::RuntimeException();
940 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
941 if ( !xLibraryStor.is() )
943 throw uno::RuntimeException();
946 catch(const uno::Exception& )
948 OSL_FAIL( "### couldn't open sub storage for library\n" );
949 return false;
953 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
955 OUString aElementName = pNames[ i ];
957 // Load binary
958 if( bLoadBinary )
960 SbModule* pMod = pBasicLib->FindModule( aElementName );
961 if( !pMod )
963 pMod = pBasicLib->MakeModule( aElementName, OUString() );
964 pBasicLib->SetModified( false );
967 OUString aCodeStreamName= aElementName;
968 aCodeStreamName += ".bin";
972 uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement(
973 aCodeStreamName,
974 embed::ElementModes::READ );
975 if ( !xCodeStream.is() )
977 throw uno::RuntimeException();
979 boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xCodeStream ));
980 if ( !pStream || pStream->GetError() )
982 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
983 throw task::ErrorCodeIOException(
984 ("utl::UcbStreamHelper::CreateStream failed for \""
985 + aCodeStreamName + "\": 0x"
986 + OUString::number(nError, 16)),
987 uno::Reference< uno::XInterface >(), nError);
990 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
991 // TODO: Check return value
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 = 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, false,
1060 INetURLObject::LAST_SEGMENT, 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, OUString() );
1084 pBasicLib->SetModified( false );
1089 OUString aCodeStreamName( "code.bin" );
1090 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
1091 aCodeStreamName,
1092 embed::ElementModes::READ );
1094 boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xCodeStream ));
1095 if ( !pStream || pStream->GetError() )
1097 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
1098 throw task::ErrorCodeIOException(
1099 ("utl::UcbStreamHelper::CreateStream failed"
1100 " for code.bin: 0x"
1101 + OUString::number(nError, 16)),
1102 uno::Reference< uno::XInterface >(),
1103 nError);
1106 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
1107 // TODO: Check return value
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 = 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 OUString& Library )
1179 throw (uno::RuntimeException, std::exception)
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;
1192 // Service
1193 OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( )
1194 throw (RuntimeException, std::exception)
1196 return OUString("com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1199 Sequence< OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( )
1200 throw (RuntimeException, std::exception)
1202 Sequence< OUString > aServiceNames( 2 );
1203 aServiceNames[0] = "com.sun.star.script.DocumentScriptLibraryContainer";
1204 // plus, for compatibility:
1205 aServiceNames[1] = "com.sun.star.script.ScriptLibraryContainer";
1206 return aServiceNames;
1209 // Implementation class SfxScriptLibrary
1211 // Ctor
1212 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1213 const Reference< XComponentContext >& xContext,
1214 const Reference< XSimpleFileAccess3 >& xSFI )
1215 : SfxLibrary( _rModifiable, cppu::UnoType<OUString>::get(), xContext, xSFI )
1216 , mbLoadedSource( false )
1217 , mbLoadedBinary( false )
1221 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1222 const Reference< XComponentContext >& xContext,
1223 const Reference< XSimpleFileAccess3 >& xSFI,
1224 const OUString& aLibInfoFileURL,
1225 const OUString& aStorageURL,
1226 bool ReadOnly )
1227 : SfxLibrary( _rModifiable, cppu::UnoType<OUString>::get(), xContext, xSFI,
1228 aLibInfoFileURL, aStorageURL, ReadOnly)
1229 , mbLoadedSource( false )
1230 , mbLoadedBinary( false )
1234 bool SfxScriptLibrary::isLoadedStorable()
1236 // note: mbLoadedSource can only be true for password-protected lib!
1237 return SfxLibrary::isLoadedStorable() && (!mbPasswordProtected || mbLoadedSource);
1240 // Provide modify state including resources
1241 bool SfxScriptLibrary::isModified()
1243 return implIsModified(); // No resources
1246 void SfxScriptLibrary::storeResources()
1248 // No resources
1251 void SfxScriptLibrary::storeResourcesToURL( const OUString& URL,
1252 const Reference< task::XInteractionHandler >& Handler )
1254 (void)URL;
1255 (void)Handler;
1258 void SfxScriptLibrary::storeResourcesAsURL
1259 ( const OUString& URL, const OUString& NewName )
1261 (void)URL;
1262 (void)NewName;
1265 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1266 < ::com::sun::star::embed::XStorage >& xStorage )
1268 // No resources
1269 (void)xStorage;
1272 bool SfxScriptLibrary::containsValidModule(const Any& rElement)
1274 OUString sModuleText;
1275 rElement >>= sModuleText;
1276 return ( !sModuleText.isEmpty() );
1279 bool SAL_CALL SfxScriptLibrary::isLibraryElementValid(const css::uno::Any& rElement) const
1281 return SfxScriptLibrary::containsValidModule(rElement);
1284 IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1285 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE );
1287 script::ModuleInfo SAL_CALL SfxScriptLibrary::getModuleInfo( const OUString& ModuleName )
1288 throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
1290 if ( !hasModuleInfo( ModuleName ) )
1292 throw NoSuchElementException();
1294 return mModuleInfos[ ModuleName ];
1297 sal_Bool SAL_CALL SfxScriptLibrary::hasModuleInfo( const OUString& ModuleName )
1298 throw (RuntimeException, std::exception)
1300 bool bRes = false;
1301 ModuleInfoMap::iterator it = mModuleInfos.find( ModuleName );
1303 if ( it != mModuleInfos.end() )
1305 bRes = true;
1307 return bRes;
1310 void SAL_CALL SfxScriptLibrary::insertModuleInfo( const OUString& ModuleName, const script::ModuleInfo& ModuleInfo )
1311 throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception)
1313 if ( hasModuleInfo( ModuleName ) )
1315 throw ElementExistException();
1317 mModuleInfos[ ModuleName ] = ModuleInfo;
1320 void SAL_CALL SfxScriptLibrary::removeModuleInfo( const OUString& ModuleName )
1321 throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
1323 // #FIXME add NoSuchElementException to the spec
1324 if ( !hasModuleInfo( ModuleName ) )
1326 throw NoSuchElementException();
1328 mModuleInfos.erase( mModuleInfos.find( ModuleName ) );
1331 } // namespace basic
1334 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
1335 com_sun_star_comp_sfx2_ScriptLibraryContainer_get_implementation(::com::sun::star::uno::XComponentContext*,
1336 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
1338 return cppu::acquire(new basic::SfxScriptLibraryContainer());
1342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */