1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scriptcont.hxx"
21 #include "sbmodule.hxx"
22 #include <com/sun/star/container/XNameContainer.hpp>
23 #include <com/sun/star/xml/sax/Parser.hpp>
24 #include <com/sun/star/xml/sax/InputSource.hpp>
25 #include <com/sun/star/xml/sax/Writer.hpp>
26 #include <com/sun/star/io/XOutputStream.hpp>
27 #include <com/sun/star/io/XInputStream.hpp>
28 #include <com/sun/star/io/XActiveDataSource.hpp>
29 #include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <com/sun/star/embed/XEncryptionProtectedSource.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/embed/XTransactedObject.hpp>
34 #include <com/sun/star/task/ErrorCodeIOException.hpp>
35 #include <com/sun/star/script/ModuleType.hpp>
36 #include <comphelper/componentcontext.hxx>
37 #include <comphelper/processfactory.hxx>
38 #include <comphelper/storagehelper.hxx>
39 #include <unotools/streamwrap.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <osl/mutex.hxx>
42 #include <rtl/digest.h>
43 #include <rtl/strbuf.hxx>
45 // For password functionality
46 #include <tools/urlobj.hxx>
49 #include <unotools/pathoptions.hxx>
50 #include <svtools/sfxecode.hxx>
51 #include <svtools/ehdl.hxx>
52 #include <basic/basmgr.hxx>
53 #include <basic/sbmod.hxx>
54 #include <basic/basicmanagerrepository.hxx>
55 #include "basic/modsizeexceeded.hxx"
56 #include <xmlscript/xmlmod_imexp.hxx>
57 #include <cppuhelper/factory.hxx>
58 #include <com/sun/star/util/VetoException.hpp>
59 #include <com/sun/star/script/XLibraryQueryExecutable.hpp>
60 #include <cppuhelper/implbase1.hxx>
64 using namespace com::sun::star::document
;
65 using namespace com::sun::star::container
;
66 using namespace com::sun::star::io
;
67 using namespace com::sun::star::uno
;
68 using namespace com::sun::star::ucb
;
69 using namespace com::sun::star::lang
;
70 using namespace com::sun::star::script
;
71 using namespace com::sun::star::xml::sax
;
72 using namespace com::sun::star
;
76 //============================================================================
77 // Implementation class SfxScriptLibraryContainer
79 const sal_Char
* SAL_CALL
SfxScriptLibraryContainer::getInfoFileName() const { return "script"; }
80 const sal_Char
* SAL_CALL
SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; }
81 const sal_Char
* SAL_CALL
SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; }
82 const sal_Char
* SAL_CALL
SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; }
84 // OldBasicPassword interface
85 void SfxScriptLibraryContainer::setLibraryPassword( const OUString
& rLibraryName
, const OUString
& rPassword
)
89 SfxLibrary
* pImplLib
= getImplLib( rLibraryName
);
90 if( !rPassword
.isEmpty() )
92 pImplLib
->mbDoc50Password
= true;
93 pImplLib
->mbPasswordProtected
= sal_True
;
94 pImplLib
->maPassword
= rPassword
;
97 catch(const NoSuchElementException
& ) {}
100 OUString
SfxScriptLibraryContainer::getLibraryPassword( const OUString
& rLibraryName
)
102 SfxLibrary
* pImplLib
= getImplLib( rLibraryName
);
104 if( pImplLib
->mbPasswordVerified
)
106 aPassword
= pImplLib
->maPassword
;
111 void SfxScriptLibraryContainer::clearLibraryPassword( const OUString
& rLibraryName
)
115 SfxLibrary
* pImplLib
= getImplLib( rLibraryName
);
116 pImplLib
->mbDoc50Password
= false;
117 pImplLib
->mbPasswordProtected
= sal_False
;
118 pImplLib
->maPassword
= OUString();
120 catch(const NoSuchElementException
& ) {}
123 sal_Bool
SfxScriptLibraryContainer::hasLibraryPassword( const OUString
& rLibraryName
)
125 SfxLibrary
* pImplLib
= getImplLib( rLibraryName
);
126 return pImplLib
->mbPasswordProtected
;
130 SfxScriptLibraryContainer::SfxScriptLibraryContainer( void )
131 :maScriptLanguage( "StarBasic" )
133 // all initialisation has to be done
134 // by calling XInitialization::initialize
137 SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference
< embed::XStorage
>& xStorage
)
138 :maScriptLanguage( "StarBasic" )
140 init( OUString(), xStorage
);
143 // Methods to get library instances of the correct type
144 SfxLibrary
* SfxScriptLibraryContainer::implCreateLibrary( const OUString
& aName
)
146 (void)aName
; // Only needed for SfxDialogLibrary
147 SfxLibrary
* pRet
= new SfxScriptLibrary( maModifiable
, mxMSF
, mxSFI
);
151 SfxLibrary
* SfxScriptLibraryContainer::implCreateLibraryLink( const OUString
& aName
,
152 const OUString
& aLibInfoFileURL
,
153 const OUString
& StorageURL
,
156 (void)aName
; // Only needed for SfxDialogLibrary
157 SfxLibrary
* pRet
= new SfxScriptLibrary( maModifiable
, mxMSF
, mxSFI
,
158 aLibInfoFileURL
, StorageURL
, ReadOnly
);
162 Any SAL_CALL
SfxScriptLibraryContainer::createEmptyLibraryElement( void )
170 bool SAL_CALL
SfxScriptLibraryContainer::isLibraryElementValid( Any aElement
) const
172 return SfxScriptLibrary::containsValidModule( aElement
);
175 void SAL_CALL
SfxScriptLibraryContainer::writeLibraryElement( const Reference
< XNameContainer
>& xLib
,
176 const OUString
& aElementName
,
177 const Reference
< XOutputStream
>& xOutput
)
181 Reference
< XWriter
> xWriter
= xml::sax::Writer::create(comphelper::getComponentContext(mxMSF
));
183 Reference
< XTruncate
> xTruncate( xOutput
, UNO_QUERY
);
184 OSL_ENSURE( xTruncate
.is(), "Currently only the streams that can be truncated are expected!" );
185 if ( xTruncate
.is() )
187 xTruncate
->truncate();
189 xWriter
->setOutputStream( xOutput
);
191 xmlscript::ModuleDescriptor aMod
;
192 aMod
.aName
= aElementName
;
193 aMod
.aLanguage
= maScriptLanguage
;
194 Any aElement
= xLib
->getByName( aElementName
);
195 aElement
>>= aMod
.aCode
;
197 Reference
< script::vba::XVBAModuleInfo
> xModInfo( xLib
, UNO_QUERY
);
198 if( xModInfo
.is() && xModInfo
->hasModuleInfo( aElementName
) )
200 script::ModuleInfo aModInfo
= xModInfo
->getModuleInfo( aElementName
);
201 switch( aModInfo
.ModuleType
)
203 case ModuleType::NORMAL
:
204 aMod
.aModuleType
= "normal";
206 case ModuleType::CLASS
:
207 aMod
.aModuleType
="class";
209 case ModuleType::FORM
:
210 aMod
.aModuleType
= "form";
212 case ModuleType::DOCUMENT
:
213 aMod
.aModuleType
= "document";
215 case ModuleType::UNKNOWN
:
221 xmlscript::exportScriptModule( xWriter
, aMod
);
225 Any SAL_CALL
SfxScriptLibraryContainer::importLibraryElement
226 ( const Reference
< XNameContainer
>& xLib
,
227 const OUString
& aElementName
, const OUString
& aFile
,
228 const uno::Reference
< io::XInputStream
>& xInStream
)
232 Reference
< XParser
> xParser
= xml::sax::Parser::create( comphelper::getComponentContext(mxMSF
) );
234 // Read from storage?
235 sal_Bool bStorage
= xInStream
.is();
236 Reference
< XInputStream
> xInput
;
246 xInput
= mxSFI
->openFileRead( aFile
);
248 catch(const Exception
& )
249 //catch( Exception& e )
252 //throw WrappedTargetException( e );
260 source
.aInputStream
= xInput
;
261 source
.sSystemId
= aFile
;
264 xmlscript::ModuleDescriptor aMod
;
268 xParser
->setDocumentHandler( ::xmlscript::importScriptModule( aMod
) );
269 xParser
->parseStream( source
);
271 catch(const Exception
& )
273 SfxErrorContext
aEc( ERRCTX_SFX_LOADBASIC
, aFile
);
274 sal_uIntPtr nErrorCode
= ERRCODE_IO_GENERAL
;
275 ErrorHandler::HandleError( nErrorCode
);
278 aRetAny
<<= aMod
.aCode
;
280 // TODO: Check language
282 // aMod.aName ignored
283 if( !aMod
.aModuleType
.isEmpty() )
285 /* If in VBA compatibility mode, force creation of the VBA Globals
286 object. Each application will create an instance of its own
287 implementation and store it in its Basic manager. Implementations
288 will do all necessary additional initialization, such as
289 registering the global "This***Doc" UNO constant, starting the
290 document events processor etc.
292 if( getVBACompatibilityMode() ) try
294 Reference
< frame::XModel
> xModel( mxOwnerDocument
); // weak-ref -> ref
295 Reference
< XMultiServiceFactory
> xFactory( xModel
, UNO_QUERY_THROW
);
296 xFactory
->createInstance( OUString( "ooo.vba.VBAGlobals" ) );
298 catch(const Exception
& )
302 script::ModuleInfo aModInfo
;
303 aModInfo
.ModuleType
= ModuleType::UNKNOWN
;
304 if( aMod
.aModuleType
== "normal" )
306 aModInfo
.ModuleType
= ModuleType::NORMAL
;
308 else if( aMod
.aModuleType
== "class" )
310 aModInfo
.ModuleType
= ModuleType::CLASS
;
312 else if( aMod
.aModuleType
== "form" )
314 aModInfo
.ModuleType
= ModuleType::FORM
;
315 aModInfo
.ModuleObject
= mxOwnerDocument
;
317 else if( aMod
.aModuleType
== "document" )
319 aModInfo
.ModuleType
= ModuleType::DOCUMENT
;
321 // #163691# use the same codename access instance for all document modules
322 if( !mxCodeNameAccess
.is() ) try
324 Reference
<frame::XModel
> xModel( mxOwnerDocument
);
325 Reference
< XMultiServiceFactory
> xSF( xModel
, UNO_QUERY_THROW
);
326 mxCodeNameAccess
.set( xSF
->createInstance( rtl::OUString("ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY
);
328 catch(const Exception
& ) {}
330 if( mxCodeNameAccess
.is() )
334 aModInfo
.ModuleObject
.set( mxCodeNameAccess
->getByName( aElementName
), uno::UNO_QUERY
);
336 catch(const uno::Exception
&)
338 OSL_TRACE("Failed to get documument object for %s", rtl::OUStringToOString( aElementName
, RTL_TEXTENCODING_UTF8
).getStr() );
343 Reference
< script::vba::XVBAModuleInfo
> xVBAModuleInfo( xLib
, UNO_QUERY
);
344 if( xVBAModuleInfo
.is() )
346 if( xVBAModuleInfo
->hasModuleInfo( aElementName
) )
348 xVBAModuleInfo
->removeModuleInfo( aElementName
);
350 xVBAModuleInfo
->insertModuleInfo( aElementName
, aModInfo
);
357 SfxLibraryContainer
* SfxScriptLibraryContainer::createInstanceImpl( void )
359 return new SfxScriptLibraryContainer();
362 void SAL_CALL
SfxScriptLibraryContainer::importFromOldStorage( const ::rtl::OUString
& aFile
)
364 // TODO: move loading from old storage to binary filters?
365 SotStorageRef xStorage
= new SotStorage( sal_False
, aFile
);
366 if( xStorage
.Is() && xStorage
->GetError() == ERRCODE_NONE
)
368 BasicManager
* pBasicManager
= new BasicManager( *(SotStorage
*)xStorage
, aFile
);
371 LibraryContainerInfo
aInfo( this, NULL
, static_cast< OldBasicPassword
* >( this ) );
372 pBasicManager
->SetLibraryContainerInfo( aInfo
);
374 // Now the libraries should be copied to this SfxScriptLibraryContainer
375 BasicManager::LegacyDeleteBasicManager( pBasicManager
);
380 // Storing with password encryption
382 // Methods XLibraryContainerPassword
383 sal_Bool SAL_CALL
SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString
& Name
)
384 throw (NoSuchElementException
, RuntimeException
)
386 LibraryContainerMethodGuard
aGuard( *this );
387 SfxLibrary
* pImplLib
= getImplLib( Name
);
388 sal_Bool bRet
= pImplLib
->mbPasswordProtected
;
392 sal_Bool SAL_CALL
SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString
& Name
)
393 throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
395 LibraryContainerMethodGuard
aGuard( *this );
396 SfxLibrary
* pImplLib
= getImplLib( Name
);
397 if( !pImplLib
->mbPasswordProtected
)
399 throw IllegalArgumentException();
401 sal_Bool bRet
= pImplLib
->mbPasswordVerified
;
405 sal_Bool SAL_CALL
SfxScriptLibraryContainer::verifyLibraryPassword
406 ( const OUString
& Name
, const OUString
& Password
)
407 throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
409 LibraryContainerMethodGuard
aGuard( *this );
410 SfxLibrary
* pImplLib
= getImplLib( Name
);
411 if( !pImplLib
->mbPasswordProtected
|| pImplLib
->mbPasswordVerified
)
413 throw IllegalArgumentException();
416 sal_Bool bSuccess
= sal_False
;
417 if( pImplLib
->mbDoc50Password
)
419 bSuccess
= ( Password
== pImplLib
->maPassword
);
422 pImplLib
->mbPasswordVerified
= sal_True
;
427 pImplLib
->maPassword
= Password
;
428 bSuccess
= implLoadPasswordLibrary( pImplLib
, Name
, sal_True
);
431 // The library gets modified by verifiying the password, because other-
432 // wise for saving the storage would be copied and that doesn't work
433 // with mtg's storages when the password is verified
434 pImplLib
->implSetModified( sal_True
);
435 pImplLib
->mbPasswordVerified
= sal_True
;
437 // Reload library to get source
438 if( pImplLib
->mbLoaded
)
440 implLoadPasswordLibrary( pImplLib
, Name
);
447 void SAL_CALL
SfxScriptLibraryContainer::changeLibraryPassword( const OUString
& Name
,
448 const OUString
& OldPassword
,
449 const OUString
& NewPassword
)
450 throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
452 LibraryContainerMethodGuard
aGuard( *this );
453 SfxLibrary
* pImplLib
= getImplLib( Name
);
454 if( OldPassword
== NewPassword
)
458 sal_Bool bOldPassword
= !OldPassword
.isEmpty();
459 sal_Bool bNewPassword
= !NewPassword
.isEmpty();
460 sal_Bool bStorage
= mxStorage
.is() && !pImplLib
->mbLink
;
462 if( pImplLib
->mbReadOnly
|| (bOldPassword
&& !pImplLib
->mbPasswordProtected
) )
464 throw IllegalArgumentException();
466 // Library must be loaded
469 sal_Bool bKillCryptedFiles
= sal_False
;
470 sal_Bool bKillUncryptedFiles
= sal_False
;
472 // Remove or change password?
475 if( isLibraryPasswordVerified( Name
) )
477 if( pImplLib
->maPassword
!= OldPassword
)
479 throw IllegalArgumentException();
484 if( !verifyLibraryPassword( Name
, OldPassword
) )
486 throw IllegalArgumentException();
488 // Reload library to get source
489 // Should be done in verifyLibraryPassword loadLibrary( Name );
494 pImplLib
->mbPasswordProtected
= sal_False
;
495 pImplLib
->mbPasswordVerified
= sal_False
;
496 pImplLib
->maPassword
= OUString();
498 maModifiable
.setModified( sal_True
);
499 pImplLib
->implSetModified( sal_True
);
501 if( !bStorage
&& !pImplLib
->mbDoc50Password
)
503 // Store application basic uncrypted
504 uno::Reference
< embed::XStorage
> xStorage
;
505 storeLibraries_Impl( xStorage
, false );
506 bKillCryptedFiles
= sal_True
;
514 pImplLib
->mbPasswordProtected
= sal_True
;
515 pImplLib
->mbPasswordVerified
= sal_True
;
516 pImplLib
->maPassword
= NewPassword
;
518 maModifiable
.setModified( sal_True
);
519 pImplLib
->implSetModified( sal_True
);
521 if( !bStorage
&& !pImplLib
->mbDoc50Password
)
523 // Store applictaion basic crypted
524 uno::Reference
< embed::XStorage
> xStorage
;
525 storeLibraries_Impl( xStorage
, false );
526 bKillUncryptedFiles
= sal_True
;
530 if( bKillCryptedFiles
|| bKillUncryptedFiles
)
532 Sequence
< OUString
> aElementNames
= pImplLib
->getElementNames();
533 sal_Int32 nNameCount
= aElementNames
.getLength();
534 const OUString
* pNames
= aElementNames
.getConstArray();
535 OUString aLibDirPath
= createAppLibraryFolder( pImplLib
, Name
);
538 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
540 OUString aElementName
= pNames
[ i
];
542 INetURLObject
aElementInetObj( aLibDirPath
);
543 aElementInetObj
.insertName( aElementName
, sal_False
,
544 INetURLObject::LAST_SEGMENT
, sal_True
,
545 INetURLObject::ENCODE_ALL
);
546 if( bKillUncryptedFiles
)
548 aElementInetObj
.setExtension( maLibElementFileExtension
);
552 aElementInetObj
.setExtension( OUString( "pba" ) );
554 OUString
aElementPath( aElementInetObj
.GetMainURL( INetURLObject::NO_DECODE
) );
556 if( mxSFI
->exists( aElementPath
) )
558 mxSFI
->kill( aElementPath
);
562 catch(const Exception
& ) {}
567 void setStreamKey( uno::Reference
< io::XStream
> xStream
, const ::rtl::OUString
& aPass
)
569 uno::Reference
< embed::XEncryptionProtectedSource
> xEncrStream( xStream
, uno::UNO_QUERY
);
570 if ( xEncrStream
.is() )
572 xEncrStream
->setEncryptionPassword( aPass
);
578 sal_Bool
SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary
* pLib
,
579 const ::rtl::OUString
& aName
,
580 const uno::Reference
< embed::XStorage
>& xStorage
,
581 const ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>& xHandler
)
583 OUString aDummyLocation
;
584 Reference
< XSimpleFileAccess3
> xDummySFA
;
585 return implStorePasswordLibrary( pLib
, aName
, xStorage
, aDummyLocation
, xDummySFA
, xHandler
);
588 sal_Bool
SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary
* pLib
, const ::rtl::OUString
& aName
,
589 const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& xStorage
,
590 const ::rtl::OUString
& aTargetURL
,
591 const Reference
< XSimpleFileAccess3
> xToUseSFI
,
592 const ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>& xHandler
)
594 bool bExport
= !aTargetURL
.isEmpty();
596 BasicManager
* pBasicMgr
= getBasicManager();
597 OSL_ENSURE( pBasicMgr
, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" );
602 // Only need to handle the export case here,
603 // save/saveas etc are handled in sfxbasemodel::storeSelf &
604 // sfxbasemodel::impl_store
605 uno::Sequence
<rtl::OUString
> aNames
;
606 if ( bExport
&& pBasicMgr
->LegacyPsswdBinaryLimitExceeded(aNames
) )
610 ModuleSizeExceeded
* pReq
= new ModuleSizeExceeded( aNames
);
611 uno::Reference
< task::XInteractionRequest
> xReq( pReq
);
612 xHandler
->handle( xReq
);
613 if ( pReq
->isAbort() )
615 throw util::VetoException();
620 StarBASIC
* pBasicLib
= pBasicMgr
->GetLib( aName
);
625 Sequence
< OUString
> aElementNames
= pLib
->getElementNames();
626 sal_Int32 nNameCount
= aElementNames
.getLength();
627 const OUString
* pNames
= aElementNames
.getConstArray();
629 sal_Bool bLink
= pLib
->mbLink
;
630 sal_Bool bStorage
= xStorage
.is() && !bLink
;
633 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
635 OUString aElementName
= pNames
[ i
];
637 // Write binary image stream
638 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
641 OUString aCodeStreamName
= aElementName
;
642 aCodeStreamName
+= ".bin";
646 uno::Reference
< io::XStream
> xCodeStream
= xStorage
->openStreamElement(
648 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
650 if ( !xCodeStream
.is() )
652 throw uno::RuntimeException();
654 SvMemoryStream aMemStream
;
655 /*sal_Bool bStore = */pMod
->StoreBinaryData( aMemStream
);
657 sal_Int32 nSize
= (sal_Int32
)aMemStream
.Tell();
658 Sequence
< sal_Int8
> aBinSeq( nSize
);
659 sal_Int8
* pData
= aBinSeq
.getArray();
660 memcpy( pData
, aMemStream
.GetData(), nSize
);
662 Reference
< XOutputStream
> xOut
= xCodeStream
->getOutputStream();
665 throw io::IOException(); // access denied because the stream is readonly
667 xOut
->writeBytes( aBinSeq
);
670 catch(const uno::Exception
& )
672 // TODO: handle error
676 if( pLib
->mbPasswordVerified
|| pLib
->mbDoc50Password
)
678 if( !isLibraryElementValid( pLib
->getByName( aElementName
) ) )
680 #if OSL_DEBUG_LEVEL > 0
681 ::rtl::OStringBuffer aMessage
;
682 aMessage
.append( "invalid library element '" );
683 aMessage
.append( ::rtl::OUStringToOString( aElementName
, osl_getThreadTextEncoding() ) );
684 aMessage
.append( "'." );
685 OSL_FAIL( aMessage
.makeStringAndClear().getStr() );
690 OUString aSourceStreamName
= aElementName
;
691 aSourceStreamName
+= ".xml";
695 uno::Reference
< io::XStream
> xSourceStream
= xStorage
->openStreamElement(
697 embed::ElementModes::READWRITE
);
698 uno::Reference
< beans::XPropertySet
> xProps( xSourceStream
, uno::UNO_QUERY
);
701 throw uno::RuntimeException();
703 OUString
aMime( "text/xml" );
704 xProps
->setPropertyValue( rtl::OUString("MediaType"), uno::makeAny( aMime
) );
706 // Set encryption key
707 setStreamKey( xSourceStream
, pLib
->maPassword
);
709 Reference
< XOutputStream
> xOutput
= xSourceStream
->getOutputStream();
710 Reference
< XNameContainer
> xLib( pLib
);
711 writeLibraryElement( xLib
, aElementName
, xOutput
);
713 catch(const uno::Exception
& )
715 OSL_FAIL( "Problem on storing of password library!\n" );
716 // TODO: error handling
719 else // !mbPasswordVerified
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
;
738 OUString aLibDirPath
;
741 INetURLObject
aInetObj( aTargetURL
);
742 aInetObj
.insertName( aName
, sal_True
, INetURLObject::LAST_SEGMENT
, sal_True
,
743 INetURLObject::ENCODE_ALL
);
744 aLibDirPath
= aInetObj
.GetMainURL( INetURLObject::NO_DECODE
);
746 if( !xSFI
->isFolder( aLibDirPath
) )
748 xSFI
->createFolder( aLibDirPath
);
753 aLibDirPath
= createAppLibraryFolder( pLib
, aName
);
756 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
758 OUString aElementName
= pNames
[ i
];
760 INetURLObject
aElementInetObj( aLibDirPath
);
761 aElementInetObj
.insertName( aElementName
, sal_False
,
762 INetURLObject::LAST_SEGMENT
, sal_True
,
763 INetURLObject::ENCODE_ALL
);
764 aElementInetObj
.setExtension( OUString( "pba" ) );
765 OUString aElementPath
= aElementInetObj
.GetMainURL( INetURLObject::NO_DECODE
);
767 if( !isLibraryElementValid( pLib
->getByName( aElementName
) ) )
769 #if OSL_DEBUG_LEVEL > 0
770 ::rtl::OStringBuffer aMessage
;
771 aMessage
.append( "invalid library element '" );
772 aMessage
.append( ::rtl::OUStringToOString( aElementName
, osl_getThreadTextEncoding() ) );
773 aMessage
.append( "'." );
774 OSL_FAIL( aMessage
.makeStringAndClear().getStr() );
781 uno::Reference
< embed::XStorage
> xElementRootStorage
=
782 ::comphelper::OStorageHelper::GetStorageFromURL(
784 embed::ElementModes::READWRITE
);
785 if ( !xElementRootStorage
.is() )
787 throw uno::RuntimeException();
789 // Write binary image stream
790 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
793 OUString
aCodeStreamName( "code.bin" );
795 uno::Reference
< io::XStream
> xCodeStream
= xElementRootStorage
->openStreamElement(
797 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
799 SvMemoryStream aMemStream
;
800 /*sal_Bool bStore = */pMod
->StoreBinaryData( aMemStream
);
802 sal_Int32 nSize
= (sal_Int32
)aMemStream
.Tell();
803 Sequence
< sal_Int8
> aBinSeq( nSize
);
804 sal_Int8
* pData
= aBinSeq
.getArray();
805 memcpy( pData
, aMemStream
.GetData(), nSize
);
807 Reference
< XOutputStream
> xOut
= xCodeStream
->getOutputStream();
810 xOut
->writeBytes( aBinSeq
);
815 // Write encrypted source stream
816 OUString
aSourceStreamName( "source.xml" );
818 uno::Reference
< io::XStream
> xSourceStream
;
821 xSourceStream
= xElementRootStorage
->openStreamElement(
823 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
825 // #87671 Allow encryption
826 uno::Reference
< embed::XEncryptionProtectedSource
> xEncr( xSourceStream
, uno::UNO_QUERY
);
827 OSL_ENSURE( xEncr
.is(),
828 "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
831 throw uno::RuntimeException();
833 xEncr
->setEncryptionPassword( pLib
->maPassword
);
835 catch(const ::com::sun::star::packages::WrongPasswordException
& )
837 xSourceStream
= xElementRootStorage
->openEncryptedStreamElement(
839 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
,
843 uno::Reference
< beans::XPropertySet
> xProps( xSourceStream
, uno::UNO_QUERY
);
846 throw uno::RuntimeException();
848 OUString
aMime( "text/xml" );
849 xProps
->setPropertyValue( rtl::OUString("MediaType"), uno::makeAny( aMime
) );
851 Reference
< XOutputStream
> xOut
= xSourceStream
->getOutputStream();
852 Reference
< XNameContainer
> xLib( pLib
);
853 writeLibraryElement( xLib
, aElementName
, xOut
);
854 // i50568: sax writer already closes stream
855 // xOut->closeOutput();
857 uno::Reference
< embed::XTransactedObject
> xTransact( xElementRootStorage
, uno::UNO_QUERY
);
858 OSL_ENSURE( xTransact
.is(), "The storage must implement XTransactedObject!\n" );
859 if ( !xTransact
.is() )
861 throw uno::RuntimeException();
866 catch(const uno::Exception
& )
868 // TODO: handle error
873 catch(const Exception
& )
880 sal_Bool
SfxScriptLibraryContainer::implLoadPasswordLibrary
881 ( SfxLibrary
* pLib
, const OUString
& Name
, sal_Bool bVerifyPasswordOnly
)
882 throw(WrappedTargetException
, RuntimeException
)
884 sal_Bool bRet
= sal_True
;
886 sal_Bool bLink
= pLib
->mbLink
;
887 sal_Bool bStorage
= mxStorage
.is() && !bLink
;
889 // Already loaded? Then only verifiedPassword can change something
890 SfxScriptLibrary
* pScriptLib
= static_cast< SfxScriptLibrary
* >( pLib
);
891 if( pScriptLib
->mbLoaded
)
893 if( pScriptLib
->mbLoadedBinary
&& !bVerifyPasswordOnly
&&
894 (pScriptLib
->mbLoadedSource
|| !pLib
->mbPasswordVerified
) )
900 StarBASIC
* pBasicLib
= NULL
;
901 sal_Bool bLoadBinary
= sal_False
;
902 if( !pScriptLib
->mbLoadedBinary
&& !bVerifyPasswordOnly
&& !pLib
->mbPasswordVerified
)
904 BasicManager
* pBasicMgr
= getBasicManager();
905 OSL_ENSURE( pBasicMgr
, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
906 sal_Bool bLoaded
= pScriptLib
->mbLoaded
;
907 pScriptLib
->mbLoaded
= sal_True
; // Necessary to get lib
908 pBasicLib
= pBasicMgr
? pBasicMgr
->GetLib( Name
) : NULL
;
909 pScriptLib
->mbLoaded
= bLoaded
; // Restore flag
914 bLoadBinary
= sal_True
;
915 pScriptLib
->mbLoadedBinary
= true;
918 sal_Bool bLoadSource
= sal_False
;
919 if( !pScriptLib
->mbLoadedSource
&& pLib
->mbPasswordVerified
&& !bVerifyPasswordOnly
)
921 bLoadSource
= sal_True
;
922 pScriptLib
->mbLoadedSource
= true;
925 Sequence
< OUString
> aElementNames
= pLib
->getElementNames();
926 sal_Int32 nNameCount
= aElementNames
.getLength();
927 const OUString
* pNames
= aElementNames
.getConstArray();
931 uno::Reference
< embed::XStorage
> xLibrariesStor
;
932 uno::Reference
< embed::XStorage
> xLibraryStor
;
936 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READ
);
937 if ( !xLibrariesStor
.is() )
939 throw uno::RuntimeException();
941 xLibraryStor
= xLibrariesStor
->openStorageElement( Name
, embed::ElementModes::READ
);
942 if ( !xLibraryStor
.is() )
944 throw uno::RuntimeException();
947 catch(const uno::Exception
& )
949 OSL_FAIL( "### couldn't open sub storage for library\n" );
954 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
956 OUString aElementName
= pNames
[ i
];
961 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
964 pMod
= pBasicLib
->MakeModule( aElementName
, String() );
965 pBasicLib
->SetModified( sal_False
);
968 OUString aCodeStreamName
= aElementName
;
969 aCodeStreamName
+= ".bin";
973 uno::Reference
< io::XStream
> xCodeStream
= xLibraryStor
->openStreamElement(
975 embed::ElementModes::READ
);
976 if ( !xCodeStream
.is() )
978 throw uno::RuntimeException();
980 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( xCodeStream
);
981 if ( !pStream
|| pStream
->GetError() )
983 sal_Int32 nError
= pStream
? pStream
->GetError() : ERRCODE_IO_GENERAL
;
985 throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), nError
);
988 /*sal_Bool bRet = */pMod
->LoadBinaryData( *pStream
);
989 // TODO: Check return value
993 catch(const uno::Exception
& )
995 // TODO: error handling
1000 if( bLoadSource
|| bVerifyPasswordOnly
)
1002 // Access encrypted source stream
1003 OUString aSourceStreamName
= aElementName
;
1004 aSourceStreamName
+= ".xml";
1008 uno::Reference
< io::XStream
> xSourceStream
= xLibraryStor
->openEncryptedStreamElement(
1010 embed::ElementModes::READ
,
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
,
1028 if( pLib
->hasByName( aElementName
) )
1030 if( aAny
.hasValue() )
1032 pLib
->maNameContainer
.replaceByName( aElementName
, aAny
);
1037 pLib
->maNameContainer
.insertByName( aElementName
, aAny
);
1041 catch(const uno::Exception
& )
1052 OUString aLibDirPath
= createAppLibraryFolder( pLib
, Name
);
1054 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
1056 OUString aElementName
= pNames
[ i
];
1058 INetURLObject
aElementInetObj( aLibDirPath
);
1059 aElementInetObj
.insertName( aElementName
, sal_False
,
1060 INetURLObject::LAST_SEGMENT
, sal_True
, INetURLObject::ENCODE_ALL
);
1061 aElementInetObj
.setExtension( OUString( "pba" ) );
1062 OUString aElementPath
= aElementInetObj
.GetMainURL( INetURLObject::NO_DECODE
);
1064 uno::Reference
< embed::XStorage
> xElementRootStorage
;
1067 xElementRootStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
1069 embed::ElementModes::READ
);
1070 } catch(const uno::Exception
& )
1072 // TODO: error handling
1075 if ( xElementRootStorage
.is() )
1080 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
1083 pMod
= pBasicLib
->MakeModule( aElementName
, String() );
1084 pBasicLib
->SetModified( sal_False
);
1089 OUString
aCodeStreamName( "code.bin" );
1090 uno::Reference
< io::XStream
> xCodeStream
= xElementRootStorage
->openStreamElement(
1092 embed::ElementModes::READ
);
1094 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( xCodeStream
);
1095 if ( !pStream
|| pStream
->GetError() )
1097 sal_Int32 nError
= pStream
? pStream
->GetError() : ERRCODE_IO_GENERAL
;
1099 throw task::ErrorCodeIOException( ::rtl::OUString(),
1100 uno::Reference
< uno::XInterface
>(),
1104 /*sal_Bool bRet = */pMod
->LoadBinaryData( *pStream
);
1105 // TODO: Check return value
1109 catch(const uno::Exception
& )
1111 // TODO: error handling
1116 if( bLoadSource
|| bVerifyPasswordOnly
)
1118 // Access encrypted source stream
1119 OUString
aSourceStreamName( "source.xml" );
1122 uno::Reference
< io::XStream
> xSourceStream
= xElementRootStorage
->openEncryptedStreamElement(
1124 embed::ElementModes::READ
,
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
,
1142 if( pLib
->hasByName( aElementName
) )
1144 if( aAny
.hasValue() )
1146 pLib
->maNameContainer
.replaceByName( aElementName
, aAny
);
1151 pLib
->maNameContainer
.insertByName( aElementName
, aAny
);
1155 catch (const uno::Exception
& )
1163 catch(const Exception
& )
1174 void SfxScriptLibraryContainer::onNewRootStorage()
1178 sal_Bool SAL_CALL
SfxScriptLibraryContainer:: HasExecutableCode( const ::rtl::OUString
& Library
)
1179 throw (uno::RuntimeException
)
1181 BasicManager
* pBasicMgr
= getBasicManager();
1182 OSL_ENSURE( pBasicMgr
, "we need a basicmanager, really we do" );
1185 return pBasicMgr
->HasExeCode( Library
); // need to change this to take name
1187 // default to it has code if we can't decide
1191 //============================================================================
1193 void createRegistryInfo_SfxScriptLibraryContainer()
1195 static OAutoRegistration
< SfxScriptLibraryContainer
> aAutoRegistration
;
1198 OUString SAL_CALL
SfxScriptLibraryContainer::getImplementationName( )
1199 throw (RuntimeException
)
1201 return getImplementationName_static();
1204 Sequence
< OUString
> SAL_CALL
SfxScriptLibraryContainer::getSupportedServiceNames( )
1205 throw (RuntimeException
)
1207 return getSupportedServiceNames_static();
1210 Sequence
< OUString
> SfxScriptLibraryContainer::getSupportedServiceNames_static()
1212 Sequence
< OUString
> aServiceNames( 2 );
1213 aServiceNames
[0] = OUString("com.sun.star.script.DocumentScriptLibraryContainer" );
1214 // plus, for compatibility:
1215 aServiceNames
[1] = OUString("com.sun.star.script.ScriptLibraryContainer" );
1216 return aServiceNames
;
1219 OUString
SfxScriptLibraryContainer::getImplementationName_static()
1221 return OUString("com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1224 Reference
< XInterface
> SAL_CALL
SfxScriptLibraryContainer::Create( const Reference
< XComponentContext
>& )
1227 Reference
< XInterface
> xRet
= static_cast< XInterface
* >( static_cast< OWeakObject
* >(new SfxScriptLibraryContainer()) );
1231 //============================================================================
1232 // Implementation class SfxScriptLibrary
1235 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper
& _rModifiable
,
1236 const Reference
< XMultiServiceFactory
>& xMSF
,
1237 const Reference
< XSimpleFileAccess3
>& xSFI
)
1238 : SfxLibrary( _rModifiable
, getCppuType( (const OUString
*)0 ), xMSF
, xSFI
)
1239 , mbLoadedSource( false )
1240 , mbLoadedBinary( false )
1244 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper
& _rModifiable
,
1245 const Reference
< XMultiServiceFactory
>& xMSF
,
1246 const Reference
< XSimpleFileAccess3
>& xSFI
,
1247 const OUString
& aLibInfoFileURL
,
1248 const OUString
& aStorageURL
,
1250 : SfxLibrary( _rModifiable
, getCppuType( (const OUString
*)0 ), xMSF
, xSFI
,
1251 aLibInfoFileURL
, aStorageURL
, ReadOnly
)
1252 , mbLoadedSource( false )
1253 , mbLoadedBinary( false )
1257 // Provide modify state including resources
1258 sal_Bool
SfxScriptLibrary::isModified( void )
1260 return implIsModified(); // No resources
1263 void SfxScriptLibrary::storeResources( void )
1268 void SfxScriptLibrary::storeResourcesToURL( const ::rtl::OUString
& URL
,
1269 const Reference
< task::XInteractionHandler
>& Handler
)
1275 void SfxScriptLibrary::storeResourcesAsURL
1276 ( const ::rtl::OUString
& URL
, const ::rtl::OUString
& NewName
)
1282 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1283 < ::com::sun::star::embed::XStorage
>& xStorage
)
1289 bool SfxScriptLibrary::containsValidModule( const Any
& aElement
)
1291 OUString sModuleText
;
1292 aElement
>>= sModuleText
;
1293 return ( !sModuleText
.isEmpty() );
1296 bool SAL_CALL
SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement
) const
1298 return SfxScriptLibrary::containsValidModule( aElement
);
1301 IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary
, SfxLibrary
, SfxScriptLibrary_BASE
);
1302 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary
, SfxLibrary
, SfxScriptLibrary_BASE
);
1304 script::ModuleInfo SAL_CALL
SfxScriptLibrary::getModuleInfo( const OUString
& ModuleName
)
1305 throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
)
1307 if ( !hasModuleInfo( ModuleName
) )
1309 throw NoSuchElementException();
1311 return mModuleInfos
[ ModuleName
];
1314 sal_Bool SAL_CALL
SfxScriptLibrary::hasModuleInfo( const OUString
& ModuleName
)
1315 throw (RuntimeException
)
1317 sal_Bool bRes
= sal_False
;
1318 ModuleInfoMap::iterator it
= mModuleInfos
.find( ModuleName
);
1320 if ( it
!= mModuleInfos
.end() )
1327 void SAL_CALL
SfxScriptLibrary::insertModuleInfo( const OUString
& ModuleName
, const script::ModuleInfo
& ModuleInfo
)
1328 throw (IllegalArgumentException
, ElementExistException
, WrappedTargetException
, RuntimeException
)
1330 if ( hasModuleInfo( ModuleName
) )
1332 throw ElementExistException();
1334 mModuleInfos
[ ModuleName
] = ModuleInfo
;
1337 void SAL_CALL
SfxScriptLibrary::removeModuleInfo( const OUString
& ModuleName
)
1338 throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
)
1340 // #FIXME add NoSuchElementException to the spec
1341 if ( !hasModuleInfo( ModuleName
) )
1343 throw NoSuchElementException();
1345 mModuleInfos
.erase( mModuleInfos
.find( ModuleName
) );
1349 //============================================================================
1351 } // namespace basic
1353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */