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