1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scriptcont.cxx,v $
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>
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>
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
;
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
);
119 if( pImplLib
->mbPasswordVerified
)
120 aPassword
= pImplLib
->maPassword
;
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
;
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
);
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
171 ( maModifiable
, mxMSF
, mxSFI
, aLibInfoFileURL
, StorageURL
, ReadOnly
);
175 Any SAL_CALL
SfxScriptLibraryContainer::createEmptyLibraryElement( void )
183 bool SAL_CALL
SfxScriptLibraryContainer::isLibraryElementValid( Any aElement
) const
185 return SfxScriptLibrary::containsValidModule( aElement
);
188 void SAL_CALL
SfxScriptLibraryContainer::writeLibraryElement
191 const OUString
& aElementName
,
192 Reference
< XOutputStream
> xOutput
197 Reference
< XExtendedDocumentHandler
> xHandler(
198 mxMSF
->createInstance(
199 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") ) ), UNO_QUERY
);
202 OSL_ENSURE( 0, "### couln't create sax-writer component\n" );
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
;
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
)
232 Reference
< XParser
> xParser( mxMSF
->createInstance(
233 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY
);
236 OSL_ENSURE( 0, "### couln't create sax parser component\n" );
241 // Read from storage?
242 sal_Bool bStorage
= xInStream
.is();
243 Reference
< XInputStream
> xInput
;
253 xInput
= mxSFI
->openFileRead( aFile
);
256 //catch( Exception& e )
259 //throw WrappedTargetException( e );
267 source
.aInputStream
= xInput
;
268 source
.sSystemId
= aFile
;
271 xmlscript::ModuleDescriptor aMod
;
275 xParser
->setDocumentHandler( ::xmlscript::importScriptModule( aMod
) );
276 xParser
->parseStream( source
);
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
289 // aMod.aName ignored
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
);
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
;
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
;
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();
352 sal_Bool bSuccess
= sal_False
;
353 if( pImplLib
->mbDoc50Password
)
355 bSuccess
= ( Password
== pImplLib
->maPassword
);
357 pImplLib
->mbPasswordVerified
= sal_True
;
361 pImplLib
->maPassword
= Password
;
362 bSuccess
= implLoadPasswordLibrary( pImplLib
, Name
, sal_True
);
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
);
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
)
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
398 sal_Bool bKillCryptedFiles
= sal_False
;
399 sal_Bool bKillUncryptedFiles
= sal_False
;
401 // Remove or change password?
404 if( isLibraryPasswordVerified( Name
) )
406 if( pImplLib
->maPassword
!= OldPassword
)
407 throw IllegalArgumentException();
411 if( !verifyLibraryPassword( Name
, OldPassword
) )
412 throw IllegalArgumentException();
414 // Reload library to get source
415 // Should be done in verifyLibraryPassword loadLibrary( Name );
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
;
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
);
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
);
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!" );
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
) )
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
);
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
;
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
);
550 //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
551 OUString aCodeStreamName
= aElementName
;
552 aCodeStreamName
+= String( RTL_CONSTASCII_USTRINGPARAM(".bin") );
555 uno::Reference
< io::XStream
> xCodeStream
= xStorage
->openStreamElement(
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();
572 throw io::IOException(); // access denied because the stream is readonly
574 xOut
->writeBytes( aBinSeq
);
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() );
598 OUString aSourceStreamName
= aElementName
;
599 aSourceStreamName
+= String( RTL_CONSTASCII_USTRINGPARAM(".xml") );
602 uno::Reference
< io::XStream
> xSourceStream
= xStorage
->openStreamElement(
604 embed::ElementModes::READWRITE
);
605 uno::Reference
< beans::XPropertySet
> xProps( xSourceStream
, uno::UNO_QUERY
);
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
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
;
645 OUString aLibDirPath
;
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
);
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() );
685 uno::Reference
< embed::XStorage
> xElementRootStorage
=
686 ::comphelper::OStorageHelper::GetStorageFromURL(
688 embed::ElementModes::READWRITE
);
689 if ( !xElementRootStorage
.is() )
690 throw uno::RuntimeException();
692 // Write binary image stream
693 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
696 OUString
aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
698 uno::Reference
< io::XStream
> xCodeStream
= xElementRootStorage
->openStreamElement(
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();
713 xOut
->writeBytes( aBinSeq
);
718 // Write encrypted source stream
719 OUString
aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") );
721 uno::Reference
< io::XStream
> xSourceStream
;
724 xSourceStream
= xElementRootStorage
->openStreamElement(
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" );
733 throw uno::RuntimeException();
734 xEncr
->setEncryptionPassword( pLib
->maPassword
);
736 catch( ::com::sun::star::packages::WrongPasswordException
& )
738 xSourceStream
= xElementRootStorage
->openEncryptedStreamElement(
740 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
,
744 uno::Reference
< beans::XPropertySet
> xProps( xSourceStream
, uno::UNO_QUERY
);
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();
763 catch( uno::Exception
& )
765 // TODO: handle error
768 // Storage Dtor commits too, that makes problems
769 // xElementRootStorage->Commit();
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
) )
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
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();
828 uno::Reference
< embed::XStorage
> xLibrariesStor
;
829 uno::Reference
< embed::XStorage
> xLibraryStor
;
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" );
848 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
850 OUString aElementName
= pNames
[ i
];
855 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
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") );
867 uno::Reference
< io::XStream
> xCodeStream
= xLibraryStor
->openStreamElement(
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
;
878 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), nError
);
881 /*BOOL bRet = */pMod
->LoadBinaryData( *pStream
);
882 // TODO: Check return value
886 catch( uno::Exception
& )
888 // TODO: error handling
893 if( bLoadSource
|| bVerifyPasswordOnly
)
895 // Access encrypted source stream
896 OUString aSourceStreamName
= aElementName
;
897 aSourceStreamName
+= String( RTL_CONSTASCII_USTRINGPARAM(".xml") );
900 uno::Reference
< io::XStream
> xSourceStream
= xLibraryStor
->openEncryptedStreamElement(
902 embed::ElementModes::READ
,
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
);
922 pLib
->maNameContainer
.insertByName( aElementName
, aAny
);
926 catch( uno::Exception
& )
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
;
951 xElementRootStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
953 embed::ElementModes::READWRITE
);
954 } catch( uno::Exception
& )
956 // TODO: error handling
959 if ( xElementRootStorage
.is() )
964 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
967 pMod
= pBasicLib
->MakeModule( aElementName
, String() );
968 pBasicLib
->SetModified( FALSE
);
972 OUString
aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") );
973 uno::Reference
< io::XStream
> xCodeStream
= xElementRootStorage
->openStreamElement(
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
;
982 throw task::ErrorCodeIOException( ::rtl::OUString(),
983 uno::Reference
< uno::XInterface
>(),
987 /*BOOL bRet = */pMod
->LoadBinaryData( *pStream
);
988 // TODO: Check return value
992 catch( uno::Exception
& )
994 // TODO: error handling
999 if( bLoadSource
|| bVerifyPasswordOnly
)
1001 // Access encrypted source stream
1002 OUString
aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") );
1004 uno::Reference
< io::XStream
> xSourceStream
= xElementRootStorage
->openEncryptedStreamElement(
1006 embed::ElementModes::READ
,
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
);
1025 pLib
->maNameContainer
.insertByName( aElementName
, aAny
);
1029 catch ( uno::Exception
& )
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;
1054 void SfxScriptLibraryContainer::onNewRootStorage()
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" );
1064 return pBasicMgr
->HasExeCode( Library
); // need to change this to take name
1065 // default to it has code if we can't decide
1069 //============================================================================
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() );
1103 aImplName
= OUString::createFromAscii( "com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1104 bNeedsInit
= sal_False
;
1109 Reference
< XInterface
> SAL_CALL
SfxScriptLibraryContainer::Create
1110 ( const Reference
< XComponentContext
>& )
1113 Reference
< XInterface
> xRet
=
1114 static_cast< XInterface
* >( static_cast< OWeakObject
* >(new SfxScriptLibraryContainer()) );
1118 //============================================================================
1119 // Implementation class SfxScriptLibrary
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
,
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 )
1155 void SfxScriptLibrary::storeResourcesToURL( const ::rtl::OUString
& URL
,
1156 const Reference
< task::XInteractionHandler
>& Handler
)
1162 void SfxScriptLibrary::storeResourcesAsURL
1163 ( const ::rtl::OUString
& URL
, const ::rtl::OUString
& NewName
)
1169 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1170 < ::com::sun::star::embed::XStorage
>& 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
;
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