merge the formfield patch from ooo-build
[ooovba.git] / basic / source / uno / scriptcont.cxx
blobad29c40f7dd36746e4f7dde6c2544a181de85ccf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scriptcont.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
33 #include "scriptcont.hxx"
34 #include "sbmodule.hxx"
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/xml/sax/XParser.hpp>
37 #include <com/sun/star/xml/sax/InputSource.hpp>
38 #include <com/sun/star/io/XOutputStream.hpp>
39 #include <com/sun/star/io/XInputStream.hpp>
40 #include <com/sun/star/io/XActiveDataSource.hpp>
41 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
42 #include <com/sun/star/embed/ElementModes.hpp>
43 #include <com/sun/star/embed/XEncryptionProtectedSource.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/embed/XTransactedObject.hpp>
46 #include <com/sun/star/task/ErrorCodeIOException.hpp>
47 #include <comphelper/processfactory.hxx>
48 #ifndef _COMPHELPER_STORAGEHELPER_HXX_
49 #include <comphelper/storagehelper.hxx>
50 #endif
51 #include <unotools/streamwrap.hxx>
52 #include <unotools/ucbstreamhelper.hxx>
53 #include <osl/mutex.hxx>
54 #include <rtl/digest.h>
55 #include <rtl/strbuf.hxx>
57 // For password functionality
58 #include <tools/urlobj.hxx>
61 #include <svtools/pathoptions.hxx>
62 #include <svtools/sfxecode.hxx>
63 #include <svtools/ehdl.hxx>
64 #include <basic/basmgr.hxx>
65 #include <basic/sbmod.hxx>
66 #include "modsizeexceeded.hxx"
67 #include <xmlscript/xmlmod_imexp.hxx>
68 #include <cppuhelper/factory.hxx>
69 #include <com/sun/star/util/VetoException.hpp>
70 #include <com/sun/star/script/XLibraryQueryExecutable.hpp>
71 #include <cppuhelper/implbase1.hxx>
72 namespace basic
75 using namespace com::sun::star::document;
76 using namespace com::sun::star::container;
77 using namespace com::sun::star::io;
78 using namespace com::sun::star::uno;
79 using namespace com::sun::star::ucb;
80 using namespace com::sun::star::lang;
81 using namespace com::sun::star::script;
82 using namespace com::sun::star::xml::sax;
83 using namespace com::sun::star;
84 using namespace cppu;
85 using namespace rtl;
86 using namespace osl;
88 using com::sun::star::uno::Reference;
90 //============================================================================
91 // Implementation class SfxScriptLibraryContainer
93 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getInfoFileName() const { return "script"; }
94 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; }
95 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; }
96 const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; }
98 // OldBasicPassword interface
99 void SfxScriptLibraryContainer::setLibraryPassword
100 ( const String& rLibraryName, const String& rPassword )
104 SfxLibrary* pImplLib = getImplLib( rLibraryName );
105 if( rPassword.Len() )
107 pImplLib->mbDoc50Password = sal_True;
108 pImplLib->mbPasswordProtected = sal_True;
109 pImplLib->maPassword = rPassword;
112 catch( NoSuchElementException& ) {}
115 String SfxScriptLibraryContainer::getLibraryPassword( const String& rLibraryName )
117 SfxLibrary* pImplLib = getImplLib( rLibraryName );
118 String aPassword;
119 if( pImplLib->mbPasswordVerified )
120 aPassword = pImplLib->maPassword;
121 return aPassword;
124 void SfxScriptLibraryContainer::clearLibraryPassword( const String& rLibraryName )
128 SfxLibrary* pImplLib = getImplLib( rLibraryName );
129 pImplLib->mbDoc50Password = sal_False;
130 pImplLib->mbPasswordProtected = sal_False;
131 pImplLib->maPassword = OUString();
133 catch( NoSuchElementException& ) {}
136 sal_Bool SfxScriptLibraryContainer::hasLibraryPassword( const String& rLibraryName )
138 SfxLibrary* pImplLib = getImplLib( rLibraryName );
139 return pImplLib->mbPasswordProtected;
142 // Ctor for service
143 SfxScriptLibraryContainer::SfxScriptLibraryContainer( void )
144 :maScriptLanguage( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) )
146 // all initialisation has to be done
147 // by calling XInitialization::initialize
150 SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference< embed::XStorage >& xStorage )
151 :maScriptLanguage( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) )
153 init( OUString(), xStorage );
156 // Methods to get library instances of the correct type
157 SfxLibrary* SfxScriptLibraryContainer::implCreateLibrary( const OUString& aName )
159 (void)aName; // Only needed for SfxDialogLibrary
160 SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxMSF, mxSFI );
161 return pRet;
164 SfxLibrary* SfxScriptLibraryContainer::implCreateLibraryLink
165 ( const OUString& aName, const OUString& aLibInfoFileURL,
166 const OUString& StorageURL, sal_Bool ReadOnly )
168 (void)aName; // Only needed for SfxDialogLibrary
169 SfxLibrary* pRet =
170 new SfxScriptLibrary
171 ( maModifiable, mxMSF, mxSFI, aLibInfoFileURL, StorageURL, ReadOnly );
172 return pRet;
175 Any SAL_CALL SfxScriptLibraryContainer::createEmptyLibraryElement( void )
177 OUString aMod;
178 Any aRetAny;
179 aRetAny <<= aMod;
180 return aRetAny;
183 bool SAL_CALL SfxScriptLibraryContainer::isLibraryElementValid( Any aElement ) const
185 return SfxScriptLibrary::containsValidModule( aElement );
188 void SAL_CALL SfxScriptLibraryContainer::writeLibraryElement
190 Any aElement,
191 const OUString& aElementName,
192 Reference< XOutputStream > xOutput
194 throw(Exception)
196 // Create sax writer
197 Reference< XExtendedDocumentHandler > xHandler(
198 mxMSF->createInstance(
199 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") ) ), UNO_QUERY );
200 if( !xHandler.is() )
202 OSL_ENSURE( 0, "### couln't create sax-writer component\n" );
203 return;
206 Reference< XTruncate > xTruncate( xOutput, UNO_QUERY );
207 OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" );
208 if ( xTruncate.is() )
209 xTruncate->truncate();
211 Reference< XActiveDataSource > xSource( xHandler, UNO_QUERY );
212 xSource->setOutputStream( xOutput );
214 xmlscript::ModuleDescriptor aMod;
215 aMod.aName = aElementName;
216 aMod.aLanguage = maScriptLanguage;
217 // make sure we export source
218 ::com::sun::star::script::ModuleInfo mInfo;
219 if ( aElement >>= mInfo )
220 aMod.aCode = mInfo.ModuleSource;
221 else
222 aElement >>= aMod.aCode;
223 xmlscript::exportScriptModule( xHandler, aMod );
227 Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement
228 ( const OUString& aFile, const uno::Reference< io::XInputStream >& xInStream )
230 Any aRetAny;
232 Reference< XParser > xParser( mxMSF->createInstance(
233 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY );
234 if( !xParser.is() )
236 OSL_ENSURE( 0, "### couln't create sax parser component\n" );
237 return aRetAny;
241 // Read from storage?
242 sal_Bool bStorage = xInStream.is();
243 Reference< XInputStream > xInput;
245 if( bStorage )
247 xInput = xInStream;
249 else
253 xInput = mxSFI->openFileRead( aFile );
255 catch( Exception& )
256 //catch( Exception& e )
258 // TODO:
259 //throw WrappedTargetException( e );
263 if( !xInput.is() )
264 return aRetAny;
266 InputSource source;
267 source.aInputStream = xInput;
268 source.sSystemId = aFile;
270 // start parsing
271 xmlscript::ModuleDescriptor aMod;
275 xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) );
276 xParser->parseStream( source );
278 catch( Exception& )
280 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile );
281 ULONG nErrorCode = ERRCODE_IO_GENERAL;
282 ErrorHandler::HandleError( nErrorCode );
285 aRetAny <<= aMod.aCode;
287 // TODO: Check language
288 // aMod.aLanguage
289 // aMod.aName ignored
291 return aRetAny;
294 SfxLibraryContainer* SfxScriptLibraryContainer::createInstanceImpl( void )
296 return new SfxScriptLibraryContainer();
299 void SAL_CALL SfxScriptLibraryContainer::importFromOldStorage( const ::rtl::OUString& aFile )
301 // TODO: move loading from old storage to binary filters?
302 SotStorageRef xStorage = new SotStorage( sal_False, aFile );
303 if( xStorage.Is() && xStorage->GetError() == ERRCODE_NONE )
305 // We need a BasicManager to avoid problems
306 // StarBASIC* pBas = new StarBASIC();
307 BasicManager* pBasicManager = new BasicManager( *(SotStorage*)xStorage, aFile );
309 // Set info
310 LibraryContainerInfo aInfo( this, NULL, static_cast< OldBasicPassword* >( this ) );
311 pBasicManager->SetLibraryContainerInfo( aInfo );
313 // Now the libraries should be copied to this SfxScriptLibraryContainer
314 BasicManager::LegacyDeleteBasicManager( pBasicManager );
319 // Storing with password encryption
321 // Methods XLibraryContainerPassword
322 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString& Name )
323 throw (NoSuchElementException, RuntimeException)
325 LibraryContainerMethodGuard aGuard( *this );
326 SfxLibrary* pImplLib = getImplLib( Name );
327 sal_Bool bRet = pImplLib->mbPasswordProtected;
328 return bRet;
331 sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString& Name )
332 throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
334 LibraryContainerMethodGuard aGuard( *this );
335 SfxLibrary* pImplLib = getImplLib( Name );
336 if( !pImplLib->mbPasswordProtected )
337 throw IllegalArgumentException();
338 sal_Bool bRet = pImplLib->mbPasswordVerified;
339 return bRet;
342 sal_Bool SAL_CALL SfxScriptLibraryContainer::verifyLibraryPassword
343 ( const OUString& Name, const OUString& Password )
344 throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
346 LibraryContainerMethodGuard aGuard( *this );
347 SfxLibrary* pImplLib = getImplLib( Name );
348 if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified )
349 throw IllegalArgumentException();
351 // Test password
352 sal_Bool bSuccess = sal_False;
353 if( pImplLib->mbDoc50Password )
355 bSuccess = ( Password == pImplLib->maPassword );
356 if( bSuccess )
357 pImplLib->mbPasswordVerified = sal_True;
359 else
361 pImplLib->maPassword = Password;
362 bSuccess = implLoadPasswordLibrary( pImplLib, Name, sal_True );
363 if( bSuccess )
365 // The library gets modified by verifiying the password, because other-
366 // wise for saving the storage would be copied and that doesn't work
367 // with mtg's storages when the password is verified
368 pImplLib->implSetModified( sal_True );
369 pImplLib->mbPasswordVerified = sal_True;
371 // Reload library to get source
372 if( pImplLib->mbLoaded )
373 implLoadPasswordLibrary( pImplLib, Name );
376 return bSuccess;
379 void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name,
380 const OUString& OldPassword, const OUString& NewPassword )
381 throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
383 LibraryContainerMethodGuard aGuard( *this );
384 SfxLibrary* pImplLib = getImplLib( Name );
385 if( OldPassword == NewPassword )
386 return;
388 sal_Bool bOldPassword = ( OldPassword.getLength() > 0 );
389 sal_Bool bNewPassword = ( NewPassword.getLength() > 0 );
390 sal_Bool bStorage = mxStorage.is() && !pImplLib->mbLink;
392 if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) )
393 throw IllegalArgumentException();
395 // Library must be loaded
396 loadLibrary( Name );
398 sal_Bool bKillCryptedFiles = sal_False;
399 sal_Bool bKillUncryptedFiles = sal_False;
401 // Remove or change password?
402 if( bOldPassword )
404 if( isLibraryPasswordVerified( Name ) )
406 if( pImplLib->maPassword != OldPassword )
407 throw IllegalArgumentException();
409 else
411 if( !verifyLibraryPassword( Name, OldPassword ) )
412 throw IllegalArgumentException();
414 // Reload library to get source
415 // Should be done in verifyLibraryPassword loadLibrary( Name );
418 if( !bNewPassword )
420 pImplLib->mbPasswordProtected = sal_False;
421 pImplLib->mbPasswordVerified = sal_False;
422 pImplLib->maPassword = OUString();
424 maModifiable.setModified( sal_True );
425 pImplLib->implSetModified( sal_True );
427 if( !bStorage && !pImplLib->mbDoc50Password )
429 // Store application basic uncrypted
430 uno::Reference< embed::XStorage > xStorage;
431 storeLibraries_Impl( xStorage, sal_False );
432 bKillCryptedFiles = sal_True;
437 // Set new password?
438 if( bNewPassword )
440 pImplLib->mbPasswordProtected = sal_True;
441 pImplLib->mbPasswordVerified = sal_True;
442 pImplLib->maPassword = NewPassword;
444 maModifiable.setModified( sal_True );
445 pImplLib->implSetModified( sal_True );
447 if( !bStorage && !pImplLib->mbDoc50Password )
449 // Store applictaion basic crypted
450 uno::Reference< embed::XStorage > xStorage;
451 storeLibraries_Impl( xStorage, sal_False );
452 bKillUncryptedFiles = sal_True;
456 if( bKillCryptedFiles || bKillUncryptedFiles )
458 Sequence< OUString > aElementNames = pImplLib->getElementNames();
459 sal_Int32 nNameCount = aElementNames.getLength();
460 const OUString* pNames = aElementNames.getConstArray();
461 OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name );
464 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
466 OUString aElementName = pNames[ i ];
468 INetURLObject aElementInetObj( aLibDirPath );
469 aElementInetObj.insertName( aElementName, sal_False,
470 INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
471 if( bKillUncryptedFiles )
472 aElementInetObj.setExtension( maLibElementFileExtension );
473 else
474 aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) );
475 String aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) );
477 if( mxSFI->exists( aElementPath ) )
478 mxSFI->kill( aElementPath );
481 catch( Exception& ) {}
486 void setStreamKey( uno::Reference< io::XStream > xStream, const ::rtl::OUString& aPass )
488 uno::Reference< embed::XEncryptionProtectedSource > xEncrStream( xStream, uno::UNO_QUERY );
489 if ( xEncrStream.is() )
490 xEncrStream->setEncryptionPassword( aPass );
494 // Impl methods
495 sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib,
496 const ::rtl::OUString& aName, const uno::Reference< embed::XStorage >& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
498 OUString aDummyLocation;
499 Reference< XSimpleFileAccess > xDummySFA;
500 return implStorePasswordLibrary( pLib, aName, xStorage, aDummyLocation, xDummySFA, xHandler );
503 sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName,
504 const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage,
505 const ::rtl::OUString& aTargetURL, const Reference< XSimpleFileAccess > xToUseSFI, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
507 bool bExport = aTargetURL.getLength();
509 BasicManager* pBasicMgr = getBasicManager();
510 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" );
511 if ( !pBasicMgr )
512 return sal_False;
514 // Only need to handle the export case here,
515 // save/saveas etc are handled in sfxbasemodel::storeSelf &
516 // sfxbasemodel::impl_store
517 uno::Sequence<rtl::OUString> aNames;
518 if ( bExport && pBasicMgr->LegacyPsswdBinaryLimitExceeded(aNames) )
520 if ( xHandler.is() )
522 ModuleSizeExceeded* pReq = new ModuleSizeExceeded( aNames );
523 uno::Reference< task::XInteractionRequest > xReq( pReq );
524 xHandler->handle( xReq );
525 if ( pReq->isAbort() )
526 throw util::VetoException();
530 StarBASIC* pBasicLib = pBasicMgr->GetLib( aName );
531 if( !pBasicLib )
532 return sal_False;
534 Sequence< OUString > aElementNames = pLib->getElementNames();
535 sal_Int32 nNameCount = aElementNames.getLength();
536 const OUString* pNames = aElementNames.getConstArray();
538 sal_Bool bLink = pLib->mbLink;
539 sal_Bool bStorage = xStorage.is() && !bLink;
540 if( bStorage )
542 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
544 OUString aElementName = pNames[ i ];
546 // Write binary image stream
547 SbModule* pMod = pBasicLib->FindModule( aElementName );
548 if( pMod )
550 //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
551 OUString aCodeStreamName = aElementName;
552 aCodeStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".bin") );
554 try {
555 uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement(
556 aCodeStreamName,
557 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
559 if ( !xCodeStream.is() )
560 throw uno::RuntimeException();
562 SvMemoryStream aMemStream;
563 /*BOOL bStore = */pMod->StoreBinaryData( aMemStream );
565 sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
566 Sequence< sal_Int8 > aBinSeq( nSize );
567 sal_Int8* pData = aBinSeq.getArray();
568 ::rtl_copyMemory( pData, aMemStream.GetData(), nSize );
570 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
571 if ( !xOut.is() )
572 throw io::IOException(); // access denied because the stream is readonly
574 xOut->writeBytes( aBinSeq );
575 xOut->closeOutput();
577 catch( uno::Exception& )
579 // TODO: handle error
583 if( pLib->mbPasswordVerified || pLib->mbDoc50Password )
585 Any aElement = pLib->getByName( aElementName );
586 if( !isLibraryElementValid( aElement ) )
588 #if OSL_DEBUG_LEVEL > 0
589 ::rtl::OStringBuffer aMessage;
590 aMessage.append( "invalid library element '" );
591 aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) );
592 aMessage.append( "'." );
593 OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() );
594 #endif
595 continue;
598 OUString aSourceStreamName = aElementName;
599 aSourceStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") );
601 try {
602 uno::Reference< io::XStream > xSourceStream = xStorage->openStreamElement(
603 aSourceStreamName,
604 embed::ElementModes::READWRITE );
605 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
606 if ( !xProps.is() )
607 throw uno::RuntimeException();
609 String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
610 OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
611 xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
613 // Set encryption key
614 setStreamKey( xSourceStream, pLib->maPassword );
616 Reference< XOutputStream > xOutput = xSourceStream->getOutputStream();
617 writeLibraryElement( aElement, aElementName, xOutput );
618 // writeLibraryElement should have the stream already closed
619 // xOutput->closeOutput();
621 catch( uno::Exception& )
623 OSL_ENSURE( sal_False, "Problem on storing of password library!\n" );
624 // TODO: error handling
627 else // !mbPasswordVerified
629 // TODO
630 // What to do if not verified?! In any case it's already loaded here
635 // Application libraries have only to be saved if the password
636 // is verified because otherwise they can't be modified
637 else if( pLib->mbPasswordVerified || bExport )
641 Reference< XSimpleFileAccess > xSFI = mxSFI;
642 if( xToUseSFI.is() )
643 xSFI = xToUseSFI;
645 OUString aLibDirPath;
646 if( bExport )
648 INetURLObject aInetObj( aTargetURL );
649 aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
650 aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
652 if( !xSFI->isFolder( aLibDirPath ) )
653 xSFI->createFolder( aLibDirPath );
655 else
657 aLibDirPath = createAppLibraryFolder( pLib, aName );
660 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
662 OUString aElementName = pNames[ i ];
664 INetURLObject aElementInetObj( aLibDirPath );
665 aElementInetObj.insertName( aElementName, sal_False,
666 INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
667 aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) );
668 String aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
670 Any aElement = pLib->getByName( aElementName );
671 if( !isLibraryElementValid( aElement ) )
673 #if OSL_DEBUG_LEVEL > 0
674 ::rtl::OStringBuffer aMessage;
675 aMessage.append( "invalid library element '" );
676 aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) );
677 aMessage.append( "'." );
678 OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() );
679 #endif
680 continue;
685 uno::Reference< embed::XStorage > xElementRootStorage =
686 ::comphelper::OStorageHelper::GetStorageFromURL(
687 aElementPath,
688 embed::ElementModes::READWRITE );
689 if ( !xElementRootStorage.is() )
690 throw uno::RuntimeException();
692 // Write binary image stream
693 SbModule* pMod = pBasicLib->FindModule( aElementName );
694 if( pMod )
696 OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
698 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
699 aCodeStreamName,
700 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
702 SvMemoryStream aMemStream;
703 /*BOOL bStore = */pMod->StoreBinaryData( aMemStream );
705 sal_Int32 nSize = (sal_Int32)aMemStream.Tell();
706 Sequence< sal_Int8 > aBinSeq( nSize );
707 sal_Int8* pData = aBinSeq.getArray();
708 ::rtl_copyMemory( pData, aMemStream.GetData(), nSize );
710 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
711 if ( xOut.is() )
713 xOut->writeBytes( aBinSeq );
714 xOut->closeOutput();
718 // Write encrypted source stream
719 OUString aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") );
721 uno::Reference< io::XStream > xSourceStream;
724 xSourceStream = xElementRootStorage->openStreamElement(
725 aSourceStreamName,
726 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
728 // #87671 Allow encryption
729 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY );
730 OSL_ENSURE( xEncr.is(),
731 "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
732 if ( !xEncr.is() )
733 throw uno::RuntimeException();
734 xEncr->setEncryptionPassword( pLib->maPassword );
736 catch( ::com::sun::star::packages::WrongPasswordException& )
738 xSourceStream = xElementRootStorage->openEncryptedStreamElement(
739 aSourceStreamName,
740 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
741 pLib->maPassword );
744 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY );
745 if ( !xProps.is() )
746 throw uno::RuntimeException();
747 String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
748 OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
749 xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
751 Reference< XOutputStream > xOut = xSourceStream->getOutputStream();
752 writeLibraryElement( aElement, aElementName, xOut );
753 // i50568: sax writer already closes stream
754 // xOut->closeOutput();
756 uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY );
757 OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" );
758 if ( !xTransact.is() )
759 throw uno::RuntimeException();
761 xTransact->commit();
763 catch( uno::Exception& )
765 // TODO: handle error
768 // Storage Dtor commits too, that makes problems
769 // xElementRootStorage->Commit();
772 catch( Exception& )
774 //throw e;
777 return sal_True;
780 sal_Bool SfxScriptLibraryContainer::implLoadPasswordLibrary
781 ( SfxLibrary* pLib, const OUString& Name, sal_Bool bVerifyPasswordOnly )
782 throw(WrappedTargetException, RuntimeException)
784 sal_Bool bRet = sal_True;
786 sal_Bool bLink = pLib->mbLink;
787 sal_Bool bStorage = mxStorage.is() && !bLink;
789 // Already loaded? Then only verifiedPassword can change something
790 SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib );
791 if( pScriptLib->mbLoaded )
793 if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly &&
794 (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) )
795 return sal_False;
798 StarBASIC* pBasicLib = NULL;
799 sal_Bool bLoadBinary = sal_False;
800 if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified )
802 BasicManager* pBasicMgr = getBasicManager();
803 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
804 sal_Bool bLoaded = pScriptLib->mbLoaded;
805 pScriptLib->mbLoaded = sal_True; // Necessary to get lib
806 pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : NULL;
807 pScriptLib->mbLoaded = bLoaded; // Restore flag
808 if( !pBasicLib )
809 return sal_False;
811 bLoadBinary = sal_True;
812 pScriptLib->mbLoadedBinary = sal_True;
815 sal_Bool bLoadSource = sal_False;
816 if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly )
818 bLoadSource = sal_True;
819 pScriptLib->mbLoadedSource = sal_True;
822 Sequence< OUString > aElementNames = pLib->getElementNames();
823 sal_Int32 nNameCount = aElementNames.getLength();
824 const OUString* pNames = aElementNames.getConstArray();
826 if( bStorage )
828 uno::Reference< embed::XStorage > xLibrariesStor;
829 uno::Reference< embed::XStorage > xLibraryStor;
830 if( bStorage )
832 try {
833 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
834 if ( !xLibrariesStor.is() )
835 throw uno::RuntimeException();
837 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
838 if ( !xLibraryStor.is() )
839 throw uno::RuntimeException();
841 catch( uno::Exception& )
843 OSL_ENSURE( 0, "### couln't open sub storage for library\n" );
844 return sal_False;
848 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
850 OUString aElementName = pNames[ i ];
852 // Load binary
853 if( bLoadBinary )
855 SbModule* pMod = pBasicLib->FindModule( aElementName );
856 if( !pMod )
858 pMod = pBasicLib->MakeModule( aElementName, String() );
859 pBasicLib->SetModified( FALSE );
862 //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
863 OUString aCodeStreamName= aElementName;
864 aCodeStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".bin") );
866 try {
867 uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement(
868 aCodeStreamName,
869 embed::ElementModes::READ );
870 if ( !xCodeStream.is() )
871 throw uno::RuntimeException();
873 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
874 if ( !pStream || pStream->GetError() )
876 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
877 delete pStream;
878 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), nError );
881 /*BOOL bRet = */pMod->LoadBinaryData( *pStream );
882 // TODO: Check return value
884 delete pStream;
886 catch( uno::Exception& )
888 // TODO: error handling
892 // Load source
893 if( bLoadSource || bVerifyPasswordOnly )
895 // Access encrypted source stream
896 OUString aSourceStreamName = aElementName;
897 aSourceStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") );
899 try {
900 uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement(
901 aSourceStreamName,
902 embed::ElementModes::READ,
903 pLib->maPassword );
904 if ( !xSourceStream.is() )
905 throw uno::RuntimeException();
907 // if this point is reached then the password is correct
908 if ( !bVerifyPasswordOnly )
910 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
911 if ( !xInStream.is() )
912 throw io::IOException(); // read access denied, seems to be impossible
914 Any aAny = importLibraryElement( aSourceStreamName, xInStream );
915 if( pLib->hasByName( aElementName ) )
917 if( aAny.hasValue() )
918 pLib->maNameContainer.replaceByName( aElementName, aAny );
920 else
922 pLib->maNameContainer.insertByName( aElementName, aAny );
926 catch( uno::Exception& )
928 bRet = sal_False;
933 else
937 OUString aLibDirPath = createAppLibraryFolder( pLib, Name );
939 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
941 OUString aElementName = pNames[ i ];
943 INetURLObject aElementInetObj( aLibDirPath );
944 aElementInetObj.insertName( aElementName, sal_False,
945 INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
946 aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) );
947 String aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE );
949 uno::Reference< embed::XStorage > xElementRootStorage;
950 try {
951 xElementRootStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
952 aElementPath,
953 embed::ElementModes::READWRITE );
954 } catch( uno::Exception& )
956 // TODO: error handling
959 if ( xElementRootStorage.is() )
961 // Load binary
962 if( bLoadBinary )
964 SbModule* pMod = pBasicLib->FindModule( aElementName );
965 if( !pMod )
967 pMod = pBasicLib->MakeModule( aElementName, String() );
968 pBasicLib->SetModified( FALSE );
971 try {
972 OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
973 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
974 aCodeStreamName,
975 embed::ElementModes::READ );
977 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream );
978 if ( !pStream || pStream->GetError() )
980 sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL;
981 delete pStream;
982 throw task::ErrorCodeIOException( ::rtl::OUString(),
983 uno::Reference< uno::XInterface >(),
984 nError );
987 /*BOOL bRet = */pMod->LoadBinaryData( *pStream );
988 // TODO: Check return value
990 delete pStream;
992 catch( uno::Exception& )
994 // TODO: error handling
998 // Load source
999 if( bLoadSource || bVerifyPasswordOnly )
1001 // Access encrypted source stream
1002 OUString aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") );
1003 try {
1004 uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement(
1005 aSourceStreamName,
1006 embed::ElementModes::READ,
1007 pLib->maPassword );
1008 if ( !xSourceStream.is() )
1009 throw uno::RuntimeException();
1011 if ( !bVerifyPasswordOnly )
1013 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1014 if ( !xInStream.is() )
1015 throw io::IOException(); // read access denied, seems to be impossible
1017 Any aAny = importLibraryElement( aSourceStreamName, xInStream );
1018 if( pLib->hasByName( aElementName ) )
1020 if( aAny.hasValue() )
1021 pLib->maNameContainer.replaceByName( aElementName, aAny );
1023 else
1025 pLib->maNameContainer.insertByName( aElementName, aAny );
1029 catch ( uno::Exception& )
1031 bRet = sal_False;
1038 catch( Exception& )
1040 // TODO
1041 //throw e;
1045 //REMOVE // If the password is verified the library must remain modified, because
1046 //REMOVE // otherwise for saving the storage would be copied and that doesn't work
1047 //REMOVE // with mtg's storages when the password is verified
1048 //REMOVE if( !pLib->mbPasswordVerified )
1049 //REMOVE pLib->mbModified = sal_False;
1050 return bRet;
1054 void SfxScriptLibraryContainer::onNewRootStorage()
1058 sal_Bool SAL_CALL
1059 SfxScriptLibraryContainer:: HasExecutableCode( const ::rtl::OUString& Library ) throw (uno::RuntimeException)
1061 BasicManager* pBasicMgr = getBasicManager();
1062 OSL_ENSURE( pBasicMgr, "we need a basicmanager, really we do" );
1063 if ( pBasicMgr )
1064 return pBasicMgr->HasExeCode( Library ); // need to change this to take name
1065 // default to it has code if we can't decide
1066 return sal_True;
1069 //============================================================================
1070 // Service
1071 void createRegistryInfo_SfxScriptLibraryContainer()
1073 static OAutoRegistration< SfxScriptLibraryContainer > aAutoRegistration;
1076 ::rtl::OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( ) throw (RuntimeException)
1078 return getImplementationName_static();
1081 Sequence< ::rtl::OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( ) throw (RuntimeException)
1083 return getSupportedServiceNames_static();
1086 Sequence< OUString > SfxScriptLibraryContainer::getSupportedServiceNames_static()
1088 Sequence< OUString > aServiceNames( 2 );
1089 aServiceNames[0] = OUString::createFromAscii( "com.sun.star.script.DocumentScriptLibraryContainer" );
1090 // plus, for compatibility:
1091 aServiceNames[1] = OUString::createFromAscii( "com.sun.star.script.ScriptLibraryContainer" );
1092 return aServiceNames;
1095 OUString SfxScriptLibraryContainer::getImplementationName_static()
1097 static OUString aImplName;
1098 static sal_Bool bNeedsInit = sal_True;
1100 MutexGuard aGuard( Mutex::getGlobalMutex() );
1101 if( bNeedsInit )
1103 aImplName = OUString::createFromAscii( "com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1104 bNeedsInit = sal_False;
1106 return aImplName;
1109 Reference< XInterface > SAL_CALL SfxScriptLibraryContainer::Create
1110 ( const Reference< XComponentContext >& )
1111 throw( Exception )
1113 Reference< XInterface > xRet =
1114 static_cast< XInterface* >( static_cast< OWeakObject* >(new SfxScriptLibraryContainer()) );
1115 return xRet;
1118 //============================================================================
1119 // Implementation class SfxScriptLibrary
1121 // Ctor
1122 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1123 const Reference< XMultiServiceFactory >& xMSF,
1124 const Reference< XSimpleFileAccess >& xSFI )
1125 : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI )
1126 , mbLoadedSource( sal_False )
1127 , mbLoadedBinary( sal_False )
1131 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1132 const Reference< XMultiServiceFactory >& xMSF,
1133 const Reference< XSimpleFileAccess >& xSFI,
1134 const OUString& aLibInfoFileURL,
1135 const OUString& aStorageURL,
1136 sal_Bool ReadOnly )
1137 : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI,
1138 aLibInfoFileURL, aStorageURL, ReadOnly)
1139 , mbLoadedSource( sal_False )
1140 , mbLoadedBinary( sal_False )
1144 // Provide modify state including resources
1145 sal_Bool SfxScriptLibrary::isModified( void )
1147 return implIsModified(); // No resources
1150 void SfxScriptLibrary::storeResources( void )
1152 // No resources
1155 void SfxScriptLibrary::storeResourcesToURL( const ::rtl::OUString& URL,
1156 const Reference< task::XInteractionHandler >& Handler )
1158 (void)URL;
1159 (void)Handler;
1162 void SfxScriptLibrary::storeResourcesAsURL
1163 ( const ::rtl::OUString& URL, const ::rtl::OUString& NewName )
1165 (void)URL;
1166 (void)NewName;
1169 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1170 < ::com::sun::star::embed::XStorage >& xStorage )
1172 // No resources
1173 (void)xStorage;
1176 bool SfxScriptLibrary::containsValidModule( const Any& aElement )
1178 OUString sModuleText;
1179 ::com::sun::star::script::ModuleInfo mInfo;
1180 if ( aElement >>= mInfo )
1181 sModuleText = mInfo.ModuleSource;
1182 else
1183 aElement >>= sModuleText;
1184 return ( sModuleText.getLength() > 0 );
1187 bool SAL_CALL SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const
1189 return SfxScriptLibrary::containsValidModule( aElement );
1192 //============================================================================
1194 } // namespace basic