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
, mxContext
, 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
, mxContext
, 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(mxContext
);
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( mxContext
);
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( 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", 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 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 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 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 OUString
& aName
,
589 const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& xStorage
,
590 const 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
<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 OString aMessage
= "invalid library element '" +
682 OUStringToOString( aElementName
, osl_getThreadTextEncoding() ) +
684 OSL_FAIL( aMessage
.getStr());
689 OUString aSourceStreamName
= aElementName
;
690 aSourceStreamName
+= ".xml";
694 uno::Reference
< io::XStream
> xSourceStream
= xStorage
->openStreamElement(
696 embed::ElementModes::READWRITE
);
697 uno::Reference
< beans::XPropertySet
> xProps( xSourceStream
, uno::UNO_QUERY
);
700 throw uno::RuntimeException();
702 OUString
aMime( "text/xml" );
703 xProps
->setPropertyValue( OUString("MediaType"), uno::makeAny( aMime
) );
705 // Set encryption key
706 setStreamKey( xSourceStream
, pLib
->maPassword
);
708 Reference
< XOutputStream
> xOutput
= xSourceStream
->getOutputStream();
709 Reference
< XNameContainer
> xLib( pLib
);
710 writeLibraryElement( xLib
, aElementName
, xOutput
);
712 catch(const uno::Exception
& )
714 OSL_FAIL( "Problem on storing of password library!\n" );
715 // TODO: error handling
718 else // !mbPasswordVerified
721 // What to do if not verified?! In any case it's already loaded here
726 // Application libraries have only to be saved if the password
727 // is verified because otherwise they can't be modified
728 else if( pLib
->mbPasswordVerified
|| bExport
)
732 Reference
< XSimpleFileAccess3
> xSFI
= mxSFI
;
737 OUString aLibDirPath
;
740 INetURLObject
aInetObj( aTargetURL
);
741 aInetObj
.insertName( aName
, sal_True
, INetURLObject::LAST_SEGMENT
, sal_True
,
742 INetURLObject::ENCODE_ALL
);
743 aLibDirPath
= aInetObj
.GetMainURL( INetURLObject::NO_DECODE
);
745 if( !xSFI
->isFolder( aLibDirPath
) )
747 xSFI
->createFolder( aLibDirPath
);
752 aLibDirPath
= createAppLibraryFolder( pLib
, aName
);
755 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
757 OUString aElementName
= pNames
[ i
];
759 INetURLObject
aElementInetObj( aLibDirPath
);
760 aElementInetObj
.insertName( aElementName
, sal_False
,
761 INetURLObject::LAST_SEGMENT
, sal_True
,
762 INetURLObject::ENCODE_ALL
);
763 aElementInetObj
.setExtension( OUString( "pba" ) );
764 OUString aElementPath
= aElementInetObj
.GetMainURL( INetURLObject::NO_DECODE
);
766 if( !isLibraryElementValid( pLib
->getByName( aElementName
) ) )
768 #if OSL_DEBUG_LEVEL > 0
769 OString aMessage
= "invalid library element '" +
770 OUStringToOString( aElementName
, osl_getThreadTextEncoding() ) +
772 OSL_FAIL( aMessage
.getStr());
779 uno::Reference
< embed::XStorage
> xElementRootStorage
=
780 ::comphelper::OStorageHelper::GetStorageFromURL(
782 embed::ElementModes::READWRITE
);
783 if ( !xElementRootStorage
.is() )
785 throw uno::RuntimeException();
787 // Write binary image stream
788 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
791 OUString
aCodeStreamName( "code.bin" );
793 uno::Reference
< io::XStream
> xCodeStream
= xElementRootStorage
->openStreamElement(
795 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
797 SvMemoryStream aMemStream
;
798 /*sal_Bool bStore = */pMod
->StoreBinaryData( aMemStream
);
800 sal_Int32 nSize
= (sal_Int32
)aMemStream
.Tell();
801 Sequence
< sal_Int8
> aBinSeq( nSize
);
802 sal_Int8
* pData
= aBinSeq
.getArray();
803 memcpy( pData
, aMemStream
.GetData(), nSize
);
805 Reference
< XOutputStream
> xOut
= xCodeStream
->getOutputStream();
808 xOut
->writeBytes( aBinSeq
);
813 // Write encrypted source stream
814 OUString
aSourceStreamName( "source.xml" );
816 uno::Reference
< io::XStream
> xSourceStream
;
819 xSourceStream
= xElementRootStorage
->openStreamElement(
821 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
823 // #87671 Allow encryption
824 uno::Reference
< embed::XEncryptionProtectedSource
> xEncr( xSourceStream
, uno::UNO_QUERY
);
825 OSL_ENSURE( xEncr
.is(),
826 "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" );
829 throw uno::RuntimeException();
831 xEncr
->setEncryptionPassword( pLib
->maPassword
);
833 catch(const ::com::sun::star::packages::WrongPasswordException
& )
835 xSourceStream
= xElementRootStorage
->openEncryptedStreamElement(
837 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
,
841 uno::Reference
< beans::XPropertySet
> xProps( xSourceStream
, uno::UNO_QUERY
);
844 throw uno::RuntimeException();
846 OUString
aMime( "text/xml" );
847 xProps
->setPropertyValue( OUString("MediaType"), uno::makeAny( aMime
) );
849 Reference
< XOutputStream
> xOut
= xSourceStream
->getOutputStream();
850 Reference
< XNameContainer
> xLib( pLib
);
851 writeLibraryElement( xLib
, aElementName
, xOut
);
852 // i50568: sax writer already closes stream
853 // xOut->closeOutput();
855 uno::Reference
< embed::XTransactedObject
> xTransact( xElementRootStorage
, uno::UNO_QUERY
);
856 OSL_ENSURE( xTransact
.is(), "The storage must implement XTransactedObject!\n" );
857 if ( !xTransact
.is() )
859 throw uno::RuntimeException();
864 catch(const uno::Exception
& )
866 // TODO: handle error
871 catch(const Exception
& )
878 sal_Bool
SfxScriptLibraryContainer::implLoadPasswordLibrary
879 ( SfxLibrary
* pLib
, const OUString
& Name
, sal_Bool bVerifyPasswordOnly
)
880 throw(WrappedTargetException
, RuntimeException
)
882 sal_Bool bRet
= sal_True
;
884 sal_Bool bLink
= pLib
->mbLink
;
885 sal_Bool bStorage
= mxStorage
.is() && !bLink
;
887 // Already loaded? Then only verifiedPassword can change something
888 SfxScriptLibrary
* pScriptLib
= static_cast< SfxScriptLibrary
* >( pLib
);
889 if( pScriptLib
->mbLoaded
)
891 if( pScriptLib
->mbLoadedBinary
&& !bVerifyPasswordOnly
&&
892 (pScriptLib
->mbLoadedSource
|| !pLib
->mbPasswordVerified
) )
898 StarBASIC
* pBasicLib
= NULL
;
899 sal_Bool bLoadBinary
= sal_False
;
900 if( !pScriptLib
->mbLoadedBinary
&& !bVerifyPasswordOnly
&& !pLib
->mbPasswordVerified
)
902 BasicManager
* pBasicMgr
= getBasicManager();
903 OSL_ENSURE( pBasicMgr
, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
904 sal_Bool bLoaded
= pScriptLib
->mbLoaded
;
905 pScriptLib
->mbLoaded
= sal_True
; // Necessary to get lib
906 pBasicLib
= pBasicMgr
? pBasicMgr
->GetLib( Name
) : NULL
;
907 pScriptLib
->mbLoaded
= bLoaded
; // Restore flag
912 bLoadBinary
= sal_True
;
913 pScriptLib
->mbLoadedBinary
= true;
916 sal_Bool bLoadSource
= sal_False
;
917 if( !pScriptLib
->mbLoadedSource
&& pLib
->mbPasswordVerified
&& !bVerifyPasswordOnly
)
919 bLoadSource
= sal_True
;
920 pScriptLib
->mbLoadedSource
= true;
923 Sequence
< OUString
> aElementNames
= pLib
->getElementNames();
924 sal_Int32 nNameCount
= aElementNames
.getLength();
925 const OUString
* pNames
= aElementNames
.getConstArray();
929 uno::Reference
< embed::XStorage
> xLibrariesStor
;
930 uno::Reference
< embed::XStorage
> xLibraryStor
;
934 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READ
);
935 if ( !xLibrariesStor
.is() )
937 throw uno::RuntimeException();
939 xLibraryStor
= xLibrariesStor
->openStorageElement( Name
, embed::ElementModes::READ
);
940 if ( !xLibraryStor
.is() )
942 throw uno::RuntimeException();
945 catch(const uno::Exception
& )
947 OSL_FAIL( "### couldn't open sub storage for library\n" );
952 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
954 OUString aElementName
= pNames
[ i
];
959 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
962 pMod
= pBasicLib
->MakeModule( aElementName
, String() );
963 pBasicLib
->SetModified( sal_False
);
966 OUString aCodeStreamName
= aElementName
;
967 aCodeStreamName
+= ".bin";
971 uno::Reference
< io::XStream
> xCodeStream
= xLibraryStor
->openStreamElement(
973 embed::ElementModes::READ
);
974 if ( !xCodeStream
.is() )
976 throw uno::RuntimeException();
978 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( xCodeStream
);
979 if ( !pStream
|| pStream
->GetError() )
981 sal_Int32 nError
= pStream
? pStream
->GetError() : ERRCODE_IO_GENERAL
;
983 throw task::ErrorCodeIOException( OUString(), uno::Reference
< uno::XInterface
>(), nError
);
986 /*sal_Bool bRet = */pMod
->LoadBinaryData( *pStream
);
987 // TODO: Check return value
991 catch(const uno::Exception
& )
993 // TODO: error handling
998 if( bLoadSource
|| bVerifyPasswordOnly
)
1000 // Access encrypted source stream
1001 OUString aSourceStreamName
= aElementName
;
1002 aSourceStreamName
+= ".xml";
1006 uno::Reference
< io::XStream
> xSourceStream
= xLibraryStor
->openEncryptedStreamElement(
1008 embed::ElementModes::READ
,
1010 if ( !xSourceStream
.is() )
1012 throw uno::RuntimeException();
1014 // if this point is reached then the password is correct
1015 if ( !bVerifyPasswordOnly
)
1017 uno::Reference
< io::XInputStream
> xInStream
= xSourceStream
->getInputStream();
1018 if ( !xInStream
.is() )
1020 throw io::IOException(); // read access denied, seems to be impossible
1022 Reference
< XNameContainer
> xLib( pLib
);
1023 Any aAny
= importLibraryElement( xLib
,
1024 aElementName
, aSourceStreamName
,
1026 if( pLib
->hasByName( aElementName
) )
1028 if( aAny
.hasValue() )
1030 pLib
->maNameContainer
.replaceByName( aElementName
, aAny
);
1035 pLib
->maNameContainer
.insertByName( aElementName
, aAny
);
1039 catch(const uno::Exception
& )
1050 OUString aLibDirPath
= createAppLibraryFolder( pLib
, Name
);
1052 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
1054 OUString aElementName
= pNames
[ i
];
1056 INetURLObject
aElementInetObj( aLibDirPath
);
1057 aElementInetObj
.insertName( aElementName
, sal_False
,
1058 INetURLObject::LAST_SEGMENT
, sal_True
, INetURLObject::ENCODE_ALL
);
1059 aElementInetObj
.setExtension( OUString( "pba" ) );
1060 OUString aElementPath
= aElementInetObj
.GetMainURL( INetURLObject::NO_DECODE
);
1062 uno::Reference
< embed::XStorage
> xElementRootStorage
;
1065 xElementRootStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
1067 embed::ElementModes::READ
);
1068 } catch(const uno::Exception
& )
1070 // TODO: error handling
1073 if ( xElementRootStorage
.is() )
1078 SbModule
* pMod
= pBasicLib
->FindModule( aElementName
);
1081 pMod
= pBasicLib
->MakeModule( aElementName
, String() );
1082 pBasicLib
->SetModified( sal_False
);
1087 OUString
aCodeStreamName( "code.bin" );
1088 uno::Reference
< io::XStream
> xCodeStream
= xElementRootStorage
->openStreamElement(
1090 embed::ElementModes::READ
);
1092 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( xCodeStream
);
1093 if ( !pStream
|| pStream
->GetError() )
1095 sal_Int32 nError
= pStream
? pStream
->GetError() : ERRCODE_IO_GENERAL
;
1097 throw task::ErrorCodeIOException( OUString(),
1098 uno::Reference
< uno::XInterface
>(),
1102 /*sal_Bool bRet = */pMod
->LoadBinaryData( *pStream
);
1103 // TODO: Check return value
1107 catch(const uno::Exception
& )
1109 // TODO: error handling
1114 if( bLoadSource
|| bVerifyPasswordOnly
)
1116 // Access encrypted source stream
1117 OUString
aSourceStreamName( "source.xml" );
1120 uno::Reference
< io::XStream
> xSourceStream
= xElementRootStorage
->openEncryptedStreamElement(
1122 embed::ElementModes::READ
,
1124 if ( !xSourceStream
.is() )
1126 throw uno::RuntimeException();
1128 if ( !bVerifyPasswordOnly
)
1130 uno::Reference
< io::XInputStream
> xInStream
= xSourceStream
->getInputStream();
1131 if ( !xInStream
.is() )
1133 throw io::IOException(); // read access denied, seems to be impossible
1135 Reference
< XNameContainer
> xLib( pLib
);
1136 Any aAny
= importLibraryElement( xLib
,
1140 if( pLib
->hasByName( aElementName
) )
1142 if( aAny
.hasValue() )
1144 pLib
->maNameContainer
.replaceByName( aElementName
, aAny
);
1149 pLib
->maNameContainer
.insertByName( aElementName
, aAny
);
1153 catch (const uno::Exception
& )
1161 catch(const Exception
& )
1172 void SfxScriptLibraryContainer::onNewRootStorage()
1176 sal_Bool SAL_CALL
SfxScriptLibraryContainer:: HasExecutableCode( const OUString
& Library
)
1177 throw (uno::RuntimeException
)
1179 BasicManager
* pBasicMgr
= getBasicManager();
1180 OSL_ENSURE( pBasicMgr
, "we need a basicmanager, really we do" );
1183 return pBasicMgr
->HasExeCode( Library
); // need to change this to take name
1185 // default to it has code if we can't decide
1189 //============================================================================
1191 void createRegistryInfo_SfxScriptLibraryContainer()
1193 static OAutoRegistration
< SfxScriptLibraryContainer
> aAutoRegistration
;
1196 OUString SAL_CALL
SfxScriptLibraryContainer::getImplementationName( )
1197 throw (RuntimeException
)
1199 return getImplementationName_static();
1202 Sequence
< OUString
> SAL_CALL
SfxScriptLibraryContainer::getSupportedServiceNames( )
1203 throw (RuntimeException
)
1205 return getSupportedServiceNames_static();
1208 Sequence
< OUString
> SfxScriptLibraryContainer::getSupportedServiceNames_static()
1210 Sequence
< OUString
> aServiceNames( 2 );
1211 aServiceNames
[0] = OUString("com.sun.star.script.DocumentScriptLibraryContainer" );
1212 // plus, for compatibility:
1213 aServiceNames
[1] = OUString("com.sun.star.script.ScriptLibraryContainer" );
1214 return aServiceNames
;
1217 OUString
SfxScriptLibraryContainer::getImplementationName_static()
1219 return OUString("com.sun.star.comp.sfx2.ScriptLibraryContainer" );
1222 Reference
< XInterface
> SAL_CALL
SfxScriptLibraryContainer::Create( const Reference
< XComponentContext
>& )
1225 Reference
< XInterface
> xRet
= static_cast< XInterface
* >( static_cast< OWeakObject
* >(new SfxScriptLibraryContainer()) );
1229 //============================================================================
1230 // Implementation class SfxScriptLibrary
1233 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper
& _rModifiable
,
1234 const Reference
< XComponentContext
>& xContext
,
1235 const Reference
< XSimpleFileAccess3
>& xSFI
)
1236 : SfxLibrary( _rModifiable
, getCppuType( (const OUString
*)0 ), xContext
, xSFI
)
1237 , mbLoadedSource( false )
1238 , mbLoadedBinary( false )
1242 SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper
& _rModifiable
,
1243 const Reference
< XComponentContext
>& xContext
,
1244 const Reference
< XSimpleFileAccess3
>& xSFI
,
1245 const OUString
& aLibInfoFileURL
,
1246 const OUString
& aStorageURL
,
1248 : SfxLibrary( _rModifiable
, getCppuType( (const OUString
*)0 ), xContext
, xSFI
,
1249 aLibInfoFileURL
, aStorageURL
, ReadOnly
)
1250 , mbLoadedSource( false )
1251 , mbLoadedBinary( false )
1255 // Provide modify state including resources
1256 sal_Bool
SfxScriptLibrary::isModified( void )
1258 return implIsModified(); // No resources
1261 void SfxScriptLibrary::storeResources( void )
1266 void SfxScriptLibrary::storeResourcesToURL( const OUString
& URL
,
1267 const Reference
< task::XInteractionHandler
>& Handler
)
1273 void SfxScriptLibrary::storeResourcesAsURL
1274 ( const OUString
& URL
, const OUString
& NewName
)
1280 void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
1281 < ::com::sun::star::embed::XStorage
>& xStorage
)
1287 bool SfxScriptLibrary::containsValidModule( const Any
& aElement
)
1289 OUString sModuleText
;
1290 aElement
>>= sModuleText
;
1291 return ( !sModuleText
.isEmpty() );
1294 bool SAL_CALL
SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement
) const
1296 return SfxScriptLibrary::containsValidModule( aElement
);
1299 IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary
, SfxLibrary
, SfxScriptLibrary_BASE
);
1300 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary
, SfxLibrary
, SfxScriptLibrary_BASE
);
1302 script::ModuleInfo SAL_CALL
SfxScriptLibrary::getModuleInfo( const OUString
& ModuleName
)
1303 throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
)
1305 if ( !hasModuleInfo( ModuleName
) )
1307 throw NoSuchElementException();
1309 return mModuleInfos
[ ModuleName
];
1312 sal_Bool SAL_CALL
SfxScriptLibrary::hasModuleInfo( const OUString
& ModuleName
)
1313 throw (RuntimeException
)
1315 sal_Bool bRes
= sal_False
;
1316 ModuleInfoMap::iterator it
= mModuleInfos
.find( ModuleName
);
1318 if ( it
!= mModuleInfos
.end() )
1325 void SAL_CALL
SfxScriptLibrary::insertModuleInfo( const OUString
& ModuleName
, const script::ModuleInfo
& ModuleInfo
)
1326 throw (IllegalArgumentException
, ElementExistException
, WrappedTargetException
, RuntimeException
)
1328 if ( hasModuleInfo( ModuleName
) )
1330 throw ElementExistException();
1332 mModuleInfos
[ ModuleName
] = ModuleInfo
;
1335 void SAL_CALL
SfxScriptLibrary::removeModuleInfo( const OUString
& ModuleName
)
1336 throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
)
1338 // #FIXME add NoSuchElementException to the spec
1339 if ( !hasModuleInfo( ModuleName
) )
1341 throw NoSuchElementException();
1343 mModuleInfos
.erase( mModuleInfos
.find( ModuleName
) );
1347 //============================================================================
1349 } // namespace basic
1351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */