LibreOffice Module basic (master) 1
scriptcont.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <scriptcont.hxx>
21#include <com/sun/star/packages/WrongPasswordException.hpp>
22#include <com/sun/star/xml/sax/Parser.hpp>
23#include <com/sun/star/xml/sax/InputSource.hpp>
24#include <com/sun/star/xml/sax/Writer.hpp>
25#include <com/sun/star/io/XTruncate.hpp>
26#include <com/sun/star/embed/ElementModes.hpp>
27#include <com/sun/star/embed/XEncryptionProtectedSource.hpp>
28#include <com/sun/star/beans/XPropertySet.hpp>
29#include <com/sun/star/embed/XTransactedObject.hpp>
30#include <com/sun/star/task/ErrorCodeIOException.hpp>
31#include <com/sun/star/script/ModuleType.hpp>
32#include <com/sun/star/lang/XMultiServiceFactory.hpp>
35#include <sal/log.hxx>
36#include <sot/storage.hxx>
37
38// For password functionality
39#include <tools/urlobj.hxx>
40
41
42#include <svtools/sfxecode.hxx>
43#include <svtools/ehdl.hxx>
44#include <basic/basmgr.hxx>
45#include <basic/sbmod.hxx>
48#include <com/sun/star/util/VetoException.hpp>
49#include <memory>
50
51namespace basic
52{
53
54using namespace com::sun::star::document;
55using namespace com::sun::star::container;
56using namespace com::sun::star::io;
57using namespace com::sun::star::uno;
58using namespace com::sun::star::ucb;
59using namespace com::sun::star::lang;
60using namespace com::sun::star::script;
61using namespace com::sun::star::xml::sax;
62using namespace com::sun::star;
63using namespace cppu;
64using namespace osl;
65
66
67// Implementation class SfxScriptLibraryContainer
68
70{
71 static constexpr OUStringLiteral script = u"script";
72 return script;
73}
75{
76 static constexpr OUStringLiteral script = u"script";
77 return script;
78}
80{
81 static constexpr OUStringLiteral xba = u"xba";
82 return xba;
83}
85{
86 static constexpr OUStringLiteral sBasic = u"Basic";
87 return sBasic;
88}
89
90void SfxScriptLibraryContainer::setLibraryPassword( const OUString& rLibraryName, const OUString& rPassword )
91{
92 try
93 {
94 SfxLibrary* pImplLib = getImplLib( rLibraryName );
95 if( !rPassword.isEmpty() )
96 {
97 pImplLib->mbDoc50Password = true;
98 pImplLib->mbPasswordProtected = true;
99 pImplLib->maPassword = rPassword;
100 SfxScriptLibrary *const pSL(dynamic_cast<SfxScriptLibrary *>(pImplLib));
101 if (pSL && pSL->mbLoaded)
102 {
103 pSL->mbLoadedSource = true; // must store source code now!
104 }
105 }
106 }
107 catch(const NoSuchElementException& ) {}
108}
109
110// Ctor for service
112{
113 // all initialisation has to be done
114 // by calling XInitialization::initialize
115}
116
118{
119 init( OUString(), xStorage );
120}
121
122// Methods to get library instances of the correct type
124{
125 return new SfxScriptLibrary( maModifiable, mxSFI );
126}
127
129 const OUString& aLibInfoFileURL,
130 const OUString& StorageURL,
131 bool ReadOnly )
132{
134 aLibInfoFileURL, StorageURL, ReadOnly );
135}
136
138{
139 Any aRetAny;
140 aRetAny <<= OUString();
141 return aRetAny;
142}
143
145{
147}
148
150 const OUString& aElementName,
151 const Reference< XOutputStream >& xOutput)
152{
153 // Create sax writer
154 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
155
156 Reference< XTruncate > xTruncate( xOutput, UNO_QUERY );
157 OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" );
158 if ( xTruncate.is() )
159 {
160 xTruncate->truncate();
161 }
162 xWriter->setOutputStream( xOutput );
163
165 aMod.aName = aElementName;
166 aMod.aLanguage = "StarBasic";
167 Any aElement = xLib->getByName( aElementName );
168 aElement >>= aMod.aCode;
169
170 Reference< script::vba::XVBAModuleInfo > xModInfo( xLib, UNO_QUERY );
171 if( xModInfo.is() && xModInfo->hasModuleInfo( aElementName ) )
172 {
173 script::ModuleInfo aModInfo = xModInfo->getModuleInfo( aElementName );
174 switch( aModInfo.ModuleType )
175 {
176 case ModuleType::NORMAL:
177 aMod.aModuleType = "normal";
178 break;
179 case ModuleType::CLASS:
180 aMod.aModuleType ="class";
181 break;
182 case ModuleType::FORM:
183 aMod.aModuleType = "form";
184 break;
185 case ModuleType::DOCUMENT:
186 aMod.aModuleType = "document";
187 break;
188 case ModuleType::UNKNOWN:
189 // nothing
190 break;
191 }
192 }
193
194 xmlscript::exportScriptModule( xWriter, aMod );
195}
196
197
199 ( const Reference < XNameContainer >& xLib,
200 const OUString& aElementName, const OUString& aFile,
201 const uno::Reference< io::XInputStream >& xInStream )
202{
203 Any aRetAny;
204
205 Reference< XParser > xParser = xml::sax::Parser::create( mxContext );
206
207 // Read from storage?
208 bool bStorage = xInStream.is();
210
211 if( bStorage )
212 {
213 xInput = xInStream;
214 }
215 else
216 {
217 try
218 {
219 xInput = mxSFI->openFileRead( aFile );
220 }
221 catch(const Exception& )
222 //catch( Exception& e )
223 {
224 // TODO:
225 //throw WrappedTargetException( e );
226 }
227 }
228
229 if( !xInput.is() )
230 return aRetAny;
231
232 InputSource source;
233 source.aInputStream = xInput;
234 source.sSystemId = aFile;
235
236 // start parsing
238
239 try
240 {
241 xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) );
242 xParser->parseStream( source );
243 }
244 catch(const Exception& )
245 {
248 }
249
250 aRetAny <<= aMod.aCode;
251
252 // TODO: Check language
253 // aMod.aLanguage
254 // aMod.aName ignored
255 if( !aMod.aModuleType.isEmpty() )
256 {
257 /* If in VBA compatibility mode, force creation of the VBA Globals
258 object. Each application will create an instance of its own
259 implementation and store it in its Basic manager. Implementations
260 will do all necessary additional initialization, such as
261 registering the global "This***Doc" UNO constant, starting the
262 document events processor etc.
263 */
264 if( getVBACompatibilityMode() ) try
265 {
268 xFactory->createInstance("ooo.vba.VBAGlobals");
269 }
270 catch(const Exception& )
271 {
272 }
273
274 script::ModuleInfo aModInfo;
275 aModInfo.ModuleType = ModuleType::UNKNOWN;
276 if( aMod.aModuleType == "normal" )
277 {
278 aModInfo.ModuleType = ModuleType::NORMAL;
279 }
280 else if( aMod.aModuleType == "class" )
281 {
282 aModInfo.ModuleType = ModuleType::CLASS;
283 }
284 else if( aMod.aModuleType == "form" )
285 {
286 aModInfo.ModuleType = ModuleType::FORM;
287 aModInfo.ModuleObject = mxOwnerDocument;
288 }
289 else if( aMod.aModuleType == "document" )
290 {
291 aModInfo.ModuleType = ModuleType::DOCUMENT;
292
293 // #163691# use the same codename access instance for all document modules
294 if( !mxCodeNameAccess.is() ) try
295 {
297 Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY_THROW );
298 mxCodeNameAccess.set( xSF->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), UNO_QUERY );
299 }
300 catch(const Exception& ) {}
301
302 if( mxCodeNameAccess.is() )
303 {
304 try
305 {
306 aModInfo.ModuleObject.set( mxCodeNameAccess->getByName( aElementName), uno::UNO_QUERY );
307 }
308 catch(const uno::Exception&)
309 {
310 SAL_WARN("basic", "Failed to get document object for " << aElementName );
311 }
312 }
313 }
314
315 Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
316 if( xVBAModuleInfo.is() )
317 {
318 if( xVBAModuleInfo->hasModuleInfo( aElementName ) )
319 {
320 xVBAModuleInfo->removeModuleInfo( aElementName );
321 }
322 xVBAModuleInfo->insertModuleInfo( aElementName, aModInfo );
323 }
324 }
325
326 return aRetAny;
327}
328
330{
331 return new SfxScriptLibraryContainer();
332}
333
335{
336 // TODO: move loading from old storage to binary filters?
337 auto xStorage = tools::make_ref<SotStorage>( false, aFile );
338 if( xStorage->GetError() == ERRCODE_NONE )
339 {
340 auto pBasicManager = std::make_unique<BasicManager> ( *xStorage, aFile );
341
342 // Set info
343 LibraryContainerInfo aInfo( this, nullptr, this );
344 pBasicManager->SetLibraryContainerInfo( aInfo );
345 }
346}
347
348
349// Storing with password encryption
350
351// Methods XLibraryContainerPassword
353{
354 LibraryContainerMethodGuard aGuard( *this );
355 SfxLibrary* pImplLib = getImplLib( Name );
356 bool bRet = pImplLib->mbPasswordProtected;
357 return bRet;
358}
359
361{
362 LibraryContainerMethodGuard aGuard( *this );
363 SfxLibrary* pImplLib = getImplLib( Name );
364 if( !pImplLib->mbPasswordProtected )
365 {
366 throw IllegalArgumentException("!passwordProtected", getXWeak(), 1);
367 }
368 bool bRet = pImplLib->mbPasswordVerified;
369 return bRet;
370}
371
373 ( const OUString& Name, const OUString& Password )
374{
375 LibraryContainerMethodGuard aGuard( *this );
376 SfxLibrary* pImplLib = getImplLib( Name );
377 if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified )
378 {
379 throw IllegalArgumentException("!PasswordProtected || PasswordVerified", getXWeak(), 1);
380 }
381 // Test password
382 bool bSuccess = false;
383 if( pImplLib->mbDoc50Password )
384 {
385 bSuccess = ( Password == pImplLib->maPassword );
386 if( bSuccess )
387 {
388 pImplLib->mbPasswordVerified = true;
389 }
390 }
391 else
392 {
393 pImplLib->maPassword = Password;
394 bSuccess = implLoadPasswordLibrary( pImplLib, Name, true );
395 if( bSuccess )
396 {
397 // The library gets modified by verifying the password, because other-
398 // wise for saving the storage would be copied and that doesn't work
399 // with mtg's storages when the password is verified
400 pImplLib->implSetModified( true );
401 pImplLib->mbPasswordVerified = true;
402
403 // Reload library to get source
404 if( pImplLib->mbLoaded )
405 {
406 implLoadPasswordLibrary( pImplLib, Name );
407 }
408 }
409 }
410 return bSuccess;
411}
412
413void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name,
414 const OUString& OldPassword,
415 const OUString& NewPassword )
416{
417 LibraryContainerMethodGuard aGuard( *this );
418 SfxLibrary* pImplLib = getImplLib( Name );
419 if( OldPassword == NewPassword )
420 {
421 return;
422 }
423 bool bOldPassword = !OldPassword.isEmpty();
424 bool bNewPassword = !NewPassword.isEmpty();
425 bool bStorage = mxStorage.is() && !pImplLib->mbLink;
426
427 if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) )
428 {
429 throw IllegalArgumentException();
430 }
431 // Library must be loaded
432 loadLibrary( Name );
433
434 bool bKillCryptedFiles = false;
435 bool bKillUnencryptedFiles = false;
436
437 // Remove or change password?
438 if( bOldPassword )
439 {
441 {
442 if( pImplLib->maPassword != OldPassword )
443 {
444 throw IllegalArgumentException();
445 }
446 }
447 else
448 {
449 if( !verifyLibraryPassword( Name, OldPassword ) )
450 {
451 throw IllegalArgumentException();
452 }
453 // Reload library to get source
454 // Should be done in verifyLibraryPassword loadLibrary( Name );
455 }
456
457 if( !bNewPassword )
458 {
459 pImplLib->mbPasswordProtected = false;
460 pImplLib->mbPasswordVerified = false;
461 pImplLib->maPassword.clear();
462
464 pImplLib->implSetModified( true );
465
466 if( !bStorage && !pImplLib->mbDoc50Password )
467 {
468 // Store application basic unencrypted
470 storeLibraries_Impl( xStorage, false );
471 bKillCryptedFiles = true;
472 }
473 }
474 }
475
476 // Set new password?
477 if( bNewPassword )
478 {
479 pImplLib->mbPasswordProtected = true;
480 pImplLib->mbPasswordVerified = true;
481 pImplLib->maPassword = NewPassword;
482 SfxScriptLibrary *const pSL(dynamic_cast<SfxScriptLibrary *>(pImplLib));
483 if (pSL && pSL->mbLoaded)
484 {
485 pSL->mbLoadedSource = true; // must store source code now!
486 }
487
489 pImplLib->implSetModified( true );
490
491 if( !bStorage && !pImplLib->mbDoc50Password )
492 {
493 // Store application basic crypted
495 storeLibraries_Impl( xStorage, false );
496 bKillUnencryptedFiles = true;
497 }
498 }
499
500 if( !(bKillCryptedFiles || bKillUnencryptedFiles) )
501 return;
502
503 Sequence< OUString > aElementNames = pImplLib->getElementNames();
504 sal_Int32 nNameCount = aElementNames.getLength();
505 const OUString* pNames = aElementNames.getConstArray();
506 OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name );
507 try
508 {
509 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
510 {
511 OUString aElementName = pNames[ i ];
512
513 INetURLObject aElementInetObj( aLibDirPath );
514 aElementInetObj.insertName( aElementName, false,
517 if( bKillUnencryptedFiles )
518 {
519 aElementInetObj.setExtension( maLibElementFileExtension );
520 }
521 else
522 {
523 aElementInetObj.setExtension( u"pba" );
524 }
525 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
526
527 if( mxSFI->exists( aElementPath ) )
528 {
529 mxSFI->kill( aElementPath );
530 }
531 }
532 }
533 catch(const Exception& ) {}
534}
535
536
537static void setStreamKey( const uno::Reference< io::XStream >& xStream, const OUString& aPass )
538{
540 if ( xEncrStream.is() )
541 {
542 xEncrStream->setEncryptionPassword( aPass );
543 }
544}
545
546
547// Impl methods
549 const OUString& aName,
550 const uno::Reference< embed::XStorage >& xStorage,
551 const css::uno::Reference< css::task::XInteractionHandler >& xHandler )
552{
554 return implStorePasswordLibrary( pLib, aName, xStorage, OUString(), xDummySFA, xHandler );
555}
556
557bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const OUString& aName,
558 const css::uno::Reference< css::embed::XStorage >& xStorage,
559 const OUString& aTargetURL,
560 const Reference< XSimpleFileAccess3 >& rToUseSFI,
561 const css::uno::Reference< css::task::XInteractionHandler >& xHandler )
562{
563 bool bExport = !aTargetURL.isEmpty();
564
565 BasicManager* pBasicMgr = getBasicManager();
566 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" );
567 if ( !pBasicMgr )
568 {
569 return false;
570 }
571 // Only need to handle the export case here,
572 // save/saveas etc are handled in sfxbasemodel::storeSelf &
573 // sfxbasemodel::impl_store
574 std::vector<OUString> aNames;
575 if ( bExport && pBasicMgr->ImgVersion12PsswdBinaryLimitExceeded(aNames) )
576 {
577 if ( xHandler.is() )
578 {
579 rtl::Reference<ModuleSizeExceeded> pReq = new ModuleSizeExceeded( aNames );
580 xHandler->handle( pReq );
581 if ( pReq->isAbort() )
582 {
583 throw util::VetoException();
584 }
585 }
586 }
587
588 StarBASIC* pBasicLib = pBasicMgr->GetLib( aName );
589 if( !pBasicLib )
590 {
591 return false;
592 }
593 Sequence< OUString > aElementNames = pLib->getElementNames();
594 sal_Int32 nNameCount = aElementNames.getLength();
595 const OUString* pNames = aElementNames.getConstArray();
596
597 bool bLink = pLib->mbLink;
598 bool bStorage = xStorage.is() && !bLink;
599 if( bStorage )
600 {
601 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
602 {
603 OUString aElementName = pNames[ i ];
604
605 // Write binary image stream
606 SbModule* pMod = pBasicLib->FindModule( aElementName );
607 if( pMod )
608 {
609 OUString aCodeStreamName = aElementName + ".bin";
610 try
611 {
612 uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement(
613 aCodeStreamName,
614 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
615
616 if ( !xCodeStream.is() )
617 {
618 throw uno::RuntimeException("null returned from openStreamElement");
619 }
620 SvMemoryStream aMemStream;
621 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
622
623 sal_Int32 const nSize = aMemStream.Tell();
624 if (nSize < 0) { abort(); }
625 Sequence< sal_Int8 > aBinSeq( nSize );
626 sal_Int8* pData = aBinSeq.getArray();
627 memcpy( pData, aMemStream.GetData(), nSize );
628
629 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
630 if ( !xOut.is() )
631 {
632 throw io::IOException(); // access denied because the stream is readonly
633 }
634 xOut->writeBytes( aBinSeq );
635 xOut->closeOutput();
636 }
637 catch(const uno::Exception& )
638 {
639 // TODO: handle error
640 }
641 }
642
643 if( pLib->mbPasswordVerified || pLib->mbDoc50Password )
644 {
645 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
646 {
647 SAL_WARN( "basic", "invalid library element '" << aElementName << "'.");
648 continue;
649 }
650
651 OUString aSourceStreamName = aElementName + ".xml";
652 try
653 {
654 uno::Reference< io::XStream > xSourceStream = xStorage->openStreamElement(
655 aSourceStreamName,
656 embed::ElementModes::READWRITE );
657 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY_THROW );
658 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
659
660 // Set encryption key
661 setStreamKey( xSourceStream, pLib->maPassword );
662
663 Reference< XOutputStream > xOutput = xSourceStream->getOutputStream();
664 Reference< XNameContainer > xLib( pLib );
665 writeLibraryElement( xLib, aElementName, xOutput );
666 }
667 catch(const uno::Exception& )
668 {
669 OSL_FAIL( "Problem on storing of password library!" );
670 // TODO: error handling
671 }
672 }
673 else // !mbPasswordVerified
674 {
675 // TODO
676 // What to do if not verified?! In any case it's already loaded here
677 }
678 }
679
680 }
681 // Application libraries have only to be saved if the password
682 // is verified because otherwise they can't be modified
683 else if( pLib->mbPasswordVerified || bExport )
684 {
685 try
686 {
688 if( rToUseSFI.is() )
689 {
690 xSFI = rToUseSFI;
691 }
692 OUString aLibDirPath;
693 if( bExport )
694 {
695 INetURLObject aInetObj( aTargetURL );
696 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT,
698 aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
699
700 if( !xSFI->isFolder( aLibDirPath ) )
701 {
702 xSFI->createFolder( aLibDirPath );
703 }
704 }
705 else
706 {
707 aLibDirPath = createAppLibraryFolder( pLib, aName );
708 }
709
710 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
711 {
712 OUString aElementName = pNames[ i ];
713
714 INetURLObject aElementInetObj( aLibDirPath );
715 aElementInetObj.insertName( aElementName, false,
718 aElementInetObj.setExtension( u"pba" );
719 OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
720
721 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
722 {
723 SAL_WARN( "basic", "invalid library element '" << aElementName << "'.");
724 continue;
725 }
726
727 try
728 {
729 uno::Reference< embed::XStorage > xElementRootStorage =
731 aElementPath,
732 embed::ElementModes::READWRITE );
733 if ( !xElementRootStorage.is() )
734 {
735 throw uno::RuntimeException("null returned from GetStorageFromURL");
736 }
737 // Write binary image stream
738 SbModule* pMod = pBasicLib->FindModule( aElementName );
739 if( pMod )
740 {
741 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
742 "code.bin",
743 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
744
745 SvMemoryStream aMemStream;
746 /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
747
748 sal_Int32 const nSize = aMemStream.Tell();
749 if (nSize < 0) { abort(); }
750 Sequence< sal_Int8 > aBinSeq( nSize );
751 sal_Int8* pData = aBinSeq.getArray();
752 memcpy( pData, aMemStream.GetData(), nSize );
753
754 Reference< XOutputStream > xOut = xCodeStream->getOutputStream();
755 if ( xOut.is() )
756 {
757 xOut->writeBytes( aBinSeq );
758 xOut->closeOutput();
759 }
760 }
761
762 // Write encrypted source stream
763 OUString aSourceStreamName( "source.xml" );
764
765 uno::Reference< io::XStream > xSourceStream;
766 try
767 {
768 xSourceStream = xElementRootStorage->openStreamElement(
769 aSourceStreamName,
770 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
771
772 // #87671 Allow encryption
773 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY_THROW );
774 xEncr->setEncryptionPassword( pLib->maPassword );
775 }
776 catch(const css::packages::WrongPasswordException& )
777 {
778 xSourceStream = xElementRootStorage->openEncryptedStreamElement(
779 aSourceStreamName,
780 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
781 pLib->maPassword );
782 }
783
784 uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY_THROW );
785 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
786
787 Reference< XOutputStream > xOut = xSourceStream->getOutputStream();
788 Reference< XNameContainer > xLib( pLib );
789 writeLibraryElement( xLib, aElementName, xOut );
790 // i50568: sax writer already closes stream
791 // xOut->closeOutput();
792
793 uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY_THROW );
794 xTransact->commit();
795 }
796 catch(const uno::Exception& )
797 {
798 // TODO: handle error
799 }
800
801 }
802 }
803 catch(const Exception& )
804 {
805 }
806 }
807 return true;
808}
809
811 ( SfxLibrary* pLib, const OUString& Name, bool bVerifyPasswordOnly )
812{
813 bool bRet = true;
814
815 bool bLink = pLib->mbLink;
816 bool bStorage = mxStorage.is() && !bLink;
817
818 // Already loaded? Then only verifiedPassword can change something
819 SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib );
820 if( pScriptLib->mbLoaded )
821 {
822 if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly &&
823 (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) )
824 {
825 return false;
826 }
827 }
828
829 StarBASIC* pBasicLib = nullptr;
830 bool bLoadBinary = false;
831 if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified )
832 {
833 BasicManager* pBasicMgr = getBasicManager();
834 OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" );
835 bool bLoaded = pScriptLib->mbLoaded;
836 pScriptLib->mbLoaded = true; // Necessary to get lib
837 pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : nullptr;
838 pScriptLib->mbLoaded = bLoaded; // Restore flag
839 if( !pBasicLib )
840 {
841 return false;
842 }
843 bLoadBinary = true;
844 pScriptLib->mbLoadedBinary = true;
845 }
846
847 bool bLoadSource = false;
848 if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly )
849 {
850 bLoadSource = true;
851 pScriptLib->mbLoadedSource = true;
852 }
853
854 Sequence< OUString > aElementNames = pLib->getElementNames();
855 sal_Int32 nNameCount = aElementNames.getLength();
856 const OUString* pNames = aElementNames.getConstArray();
857
858 if( bStorage )
859 {
862 try {
863 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
864 if ( !xLibrariesStor.is() )
865 {
866 throw uno::RuntimeException("null returned from openStorageElement");
867 }
868 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
869 if ( !xLibraryStor.is() )
870 {
871 throw uno::RuntimeException("null returned from openStorageElement");
872 }
873 }
874 catch(const uno::Exception& )
875 {
876 OSL_FAIL( "### couldn't open sub storage for library" );
877 return false;
878 }
879
880 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
881 {
882 OUString aElementName = pNames[ i ];
883
884 // Load binary
885 if( bLoadBinary )
886 {
887 SbModule* pMod = pBasicLib->FindModule( aElementName );
888 if( !pMod )
889 {
890 pMod = pBasicLib->MakeModule( aElementName, OUString() );
891 pBasicLib->SetModified( false );
892 }
893
894 OUString aCodeStreamName= aElementName + ".bin";
895 try
896 {
897 uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement(
898 aCodeStreamName,
900 if ( !xCodeStream.is() )
901 {
902 throw uno::RuntimeException("null returned from openStreamElement");
903 }
904 std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xCodeStream ));
905 if ( !pStream || pStream->GetError() )
906 {
907 sal_uInt32 nError = sal_uInt32(pStream ? pStream->GetError() : ERRCODE_IO_GENERAL);
908 throw task::ErrorCodeIOException(
909 ("utl::UcbStreamHelper::CreateStream failed for \""
910 + aCodeStreamName + "\": 0x"
911 + OUString::number(nError, 16)),
913 }
914
915 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
916 // TODO: Check return value
917 }
918 catch(const uno::Exception& )
919 {
920 // TODO: error handling
921 }
922 }
923
924 // Load source
925 if( bLoadSource || bVerifyPasswordOnly )
926 {
927 // Access encrypted source stream
928 OUString aSourceStreamName = aElementName + ".xml";
929 try
930 {
931 uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement(
932 aSourceStreamName,
934 pLib->maPassword );
935 if ( !xSourceStream.is() )
936 {
937 throw uno::RuntimeException("null returned from openEncryptedStreamElement");
938 }
939 // if this point is reached then the password is correct
940 if ( !bVerifyPasswordOnly )
941 {
942 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
943 if ( !xInStream.is() )
944 {
945 throw io::IOException(); // read access denied, seems to be impossible
946 }
948 Any aAny = importLibraryElement( xLib,
949 aElementName, aSourceStreamName,
950 xInStream );
951 if( pLib->hasByName( aElementName ) )
952 {
953 if( aAny.hasValue() )
954 {
955 pLib->maNameContainer->replaceByName( aElementName, aAny );
956 }
957 }
958 else
959 {
960 pLib->maNameContainer->insertByName( aElementName, aAny );
961 }
962 }
963 }
964 catch(const uno::Exception& )
965 {
966 bRet = false;
967 }
968 }
969 }
970 }
971 else
972 {
973 try
974 {
975 OUString aLibDirPath = createAppLibraryFolder( pLib, Name );
976
977 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
978 {
979 OUString aElementName = pNames[ i ];
980
981 INetURLObject aElementInetObj( aLibDirPath );
982 aElementInetObj.insertName( aElementName, false,
984 aElementInetObj.setExtension( u"pba" );
985 OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
986
987 uno::Reference< embed::XStorage > xElementRootStorage;
988 try
989 {
991 aElementPath,
993 } catch(const uno::Exception& )
994 {
995 // TODO: error handling
996 }
997
998 if ( xElementRootStorage.is() )
999 {
1000 // Load binary
1001 if( bLoadBinary )
1002 {
1003 SbModule* pMod = pBasicLib->FindModule( aElementName );
1004 if( !pMod )
1005 {
1006 pMod = pBasicLib->MakeModule( aElementName, OUString() );
1007 pBasicLib->SetModified( false );
1008 }
1009
1010 try
1011 {
1012 uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement(
1013 "code.bin",
1015
1016 std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xCodeStream ));
1017 if ( !pStream || pStream->GetError() )
1018 {
1019 sal_uInt32 nError = sal_uInt32(pStream ? pStream->GetError() : ERRCODE_IO_GENERAL);
1020 throw task::ErrorCodeIOException(
1021 ("utl::UcbStreamHelper::CreateStream failed"
1022 " for code.bin: 0x"
1023 + OUString::number(nError, 16)),
1025 nError);
1026 }
1027
1028 /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream );
1029 // TODO: Check return value
1030 }
1031 catch(const uno::Exception& )
1032 {
1033 // TODO: error handling
1034 }
1035 }
1036
1037 // Load source
1038 if( bLoadSource || bVerifyPasswordOnly )
1039 {
1040 // Access encrypted source stream
1041 try
1042 {
1043 OUString aSourceStreamName( "source.xml" );
1044 uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement(
1045 aSourceStreamName,
1047 pLib->maPassword );
1048 if ( !xSourceStream.is() )
1049 {
1050 throw uno::RuntimeException("null returned from openEncryptedStreamElement");
1051 }
1052 if ( !bVerifyPasswordOnly )
1053 {
1054 uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream();
1055 if ( !xInStream.is() )
1056 {
1057 throw io::IOException(); // read access denied, seems to be impossible
1058 }
1060 Any aAny = importLibraryElement( xLib,
1061 aElementName,
1062 aSourceStreamName,
1063 xInStream );
1064 if( pLib->hasByName( aElementName ) )
1065 {
1066 if( aAny.hasValue() )
1067 {
1068 pLib->maNameContainer->replaceByName( aElementName, aAny );
1069 }
1070 }
1071 else
1072 {
1073 pLib->maNameContainer->insertByName( aElementName, aAny );
1074 }
1075 }
1076 }
1077 catch (const uno::Exception& )
1078 {
1079 bRet = false;
1080 }
1081 }
1082 }
1083 }
1084 }
1085 catch(const Exception& )
1086 {
1087 // TODO
1088 //throw e;
1089 }
1090 }
1091
1092 return bRet;
1093}
1094
1095
1097{
1098}
1099
1101{
1102 BasicManager* pBasicMgr = getBasicManager();
1103 OSL_ENSURE( pBasicMgr, "we need a basicmanager, really we do" );
1104 if ( pBasicMgr )
1105 {
1106 return pBasicMgr->HasExeCode( Library ); // need to change this to take name
1107 }
1108 // default to it has code if we can't decide
1109 return true;
1110}
1111
1112
1113// Service
1115{
1116 return "com.sun.star.comp.sfx2.ScriptLibraryContainer";
1117}
1118
1120{
1121 return {"com.sun.star.script.DocumentScriptLibraryContainer",
1122 "com.sun.star.script.ScriptLibraryContainer"}; // for compatibility
1123}
1124
1125// Implementation class SfxScriptLibrary
1126
1127// Ctor
1130 : SfxLibrary( _rModifiable, cppu::UnoType<OUString>::get(), xSFI )
1131 , mbLoadedSource( false )
1132 , mbLoadedBinary( false )
1133{
1134}
1135
1136SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable,
1138 const OUString& aLibInfoFileURL,
1139 const OUString& aStorageURL,
1140 bool ReadOnly )
1141 : SfxLibrary( _rModifiable, cppu::UnoType<OUString>::get(), xSFI,
1142 aLibInfoFileURL, aStorageURL, ReadOnly)
1143 , mbLoadedSource( false )
1144 , mbLoadedBinary( false )
1145{
1146}
1147
1149{
1150 // note: mbLoadedSource can only be true for password-protected lib!
1152}
1153
1154// Provide modify state including resources
1156{
1157 return implIsModified(); // No resources
1158}
1159
1161{
1162 // No resources
1163}
1164
1167{}
1168
1170 ( const OUString&, const OUString& )
1171{}
1172
1173void SfxScriptLibrary::storeResourcesToStorage( const css::uno::Reference
1174 < css::embed::XStorage >& )
1175{
1176 // No resources
1177}
1178
1180{
1181 OUString sModuleText;
1182 rElement >>= sModuleText;
1183 return ( !sModuleText.isEmpty() );
1184}
1185
1186bool SfxScriptLibrary::isLibraryElementValid(const css::uno::Any& rElement) const
1187{
1189}
1190
1193
1194script::ModuleInfo SAL_CALL SfxScriptLibrary::getModuleInfo( const OUString& ModuleName )
1195{
1196 if ( !hasModuleInfo( ModuleName ) )
1197 {
1198 throw NoSuchElementException();
1199 }
1200 return mModuleInfo[ ModuleName ];
1201}
1202
1203sal_Bool SAL_CALL SfxScriptLibrary::hasModuleInfo( const OUString& ModuleName )
1204{
1205 bool bRes = false;
1206 ModuleInfoMap::iterator it = mModuleInfo.find( ModuleName );
1207
1208 if ( it != mModuleInfo.end() )
1209 {
1210 bRes = true;
1211 }
1212 return bRes;
1213}
1214
1215void SAL_CALL SfxScriptLibrary::insertModuleInfo( const OUString& ModuleName, const script::ModuleInfo& ModuleInfo )
1216{
1217 if ( hasModuleInfo( ModuleName ) )
1218 {
1219 throw ElementExistException();
1220 }
1221 mModuleInfo[ ModuleName ] = ModuleInfo;
1222}
1223
1224void SAL_CALL SfxScriptLibrary::removeModuleInfo( const OUString& ModuleName )
1225{
1226 // #FIXME add NoSuchElementException to the spec
1227 if ( mModuleInfo.erase( ModuleName ) == 0 )
1228 throw NoSuchElementException();
1229}
1230
1231} // namespace basic
1232
1233
1234extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1236 css::uno::Sequence<css::uno::Any> const &)
1237{
1238 return cppu::acquire(new basic::SfxScriptLibraryContainer());
1239}
1240
1241
1242/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XInputStream > xStream
sal_Int16 script
StarBASIC * GetLib(sal_uInt16 nLib) const
Definition: basmgr.cxx:1169
bool HasExeCode(std::u16string_view)
Definition: basmgr.cxx:814
bool ImgVersion12PsswdBinaryLimitExceeded(std::vector< OUString > &_out_rModuleNames)
determines whether there are password-protected modules whose size exceeds the B_IMG_VERSION_12 modul...
Definition: basmgr.cxx:1393
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool insertName(std::u16string_view rTheName, bool bAppendFinalSlash=false, sal_Int32 nIndex=LAST_SEGMENT, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
bool setExtension(std::u16string_view rTheExtension, sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
SAL_DLLPRIVATE void LoadBinaryData(SvStream &)
Definition: sbxmod.cxx:1786
SAL_DLLPRIVATE void StoreBinaryData(SvStream &)
Definition: sbxmod.cxx:1765
SbModule * MakeModule(const OUString &rName, const OUString &rSrc)
Definition: sb.cxx:1012
SbModule * FindModule(std::u16string_view)
Definition: sb.cxx:1092
virtual void SetModified(bool) override
Definition: sb.cxx:931
const void * GetData()
sal_uInt64 Tell() const
void setModified(bool _bModified)
Definition: namecont.cxx:327
OUString maLibElementFileExtension
Definition: namecont.hxx:202
OUString createAppLibraryFolder(SfxLibrary *pLib, std::u16string_view aName)
Definition: namecont.cxx:1323
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: namecont.hxx:188
void init(const OUString &rInitialDocumentURL, const css::uno::Reference< css::embed::XStorage > &_rxInitialStorage)
Definition: namecont.cxx:576
virtual void SAL_CALL loadLibrary(const OUString &Name) override
Definition: namecont.cxx:2283
css::uno::Reference< css::ucb::XSimpleFileAccess3 > mxSFI
Definition: namecont.hxx:189
css::uno::Reference< css::embed::XStorage > mxStorage
Definition: namecont.hxx:206
virtual sal_Bool SAL_CALL getVBACompatibilityMode() override
Definition: namecont.cxx:2789
ModifiableHelper maModifiable
Definition: namecont.hxx:193
BasicManager * getBasicManager()
Definition: namecont.cxx:388
void storeLibraries_Impl(const css::uno::Reference< css::embed::XStorage > &xStorage, bool bComplete)
Definition: namecont.cxx:1728
SfxLibrary * getImplLib(const OUString &rLibraryName)
Definition: namecont.cxx:1283
css::uno::WeakReference< css::frame::XModel > mxOwnerDocument
Definition: namecont.hxx:191
bool implIsModified() const
Definition: namecont.hxx:520
virtual bool isLoadedStorable()
Definition: namecont.cxx:2979
OUString maPassword
Definition: namecont.hxx:505
bool mbPasswordProtected
Definition: namecont.hxx:501
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
Definition: namecont.cxx:3036
void implSetModified(bool _bIsModified)
Definition: namecont.cxx:2984
virtual css::uno::Any createEmptyLibraryElement() override
Definition: scriptcont.cxx:137
virtual void SAL_CALL changeLibraryPassword(const OUString &Name, const OUString &OldPassword, const OUString &NewPassword) override
Definition: scriptcont.cxx:413
virtual sal_Bool SAL_CALL isLibraryPasswordProtected(const OUString &Name) override
Definition: scriptcont.cxx:352
virtual rtl::Reference< SfxLibrary > implCreateLibraryLink(const OUString &aName, const OUString &aLibInfoFileURL, const OUString &StorageURL, bool ReadOnly) override
Definition: scriptcont.cxx:128
virtual rtl::Reference< SfxLibrary > implCreateLibrary(const OUString &aName) override
Definition: scriptcont.cxx:123
virtual bool implLoadPasswordLibrary(SfxLibrary *pLib, const OUString &Name, bool bVerifyPasswordOnly=false) override
Definition: scriptcont.cxx:811
virtual OUString getOldInfoFileName() const override
Definition: scriptcont.cxx:74
virtual bool isLibraryElementValid(const css::uno::Any &rElement) const override
Definition: scriptcont.cxx:144
virtual css::uno::Any importLibraryElement(const css::uno::Reference< css::container::XNameContainer > &xLibrary, const OUString &aElementName, const OUString &aFile, const css::uno::Reference< css::io::XInputStream > &xElementStream) override
Definition: scriptcont.cxx:199
virtual OUString getInfoFileName() const override
Definition: scriptcont.cxx:69
virtual bool implStorePasswordLibrary(SfxLibrary *pLib, const OUString &aName, const css::uno::Reference< css::embed::XStorage > &xStorage, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
css::uno::Reference< css::container::XNameAccess > mxCodeNameAccess
Definition: scriptcont.hxx:34
virtual OUString getLibElementFileExtension() const override
Definition: scriptcont.cxx:79
void setLibraryPassword(const OUString &rLibraryName, const OUString &rPassword)
Definition: scriptcont.cxx:90
virtual OUString getLibrariesDir() const override
Definition: scriptcont.cxx:84
virtual sal_Bool SAL_CALL verifyLibraryPassword(const OUString &Name, const OUString &Password) override
Definition: scriptcont.cxx:373
virtual void importFromOldStorage(const OUString &aFile) override
Definition: scriptcont.cxx:334
virtual rtl::Reference< SfxLibraryContainer > createInstanceImpl() override
Definition: scriptcont.cxx:329
virtual void writeLibraryElement(const css::uno::Reference< css::container::XNameContainer > &xLibrary, const OUString &aElementName, const css::uno::Reference< css::io::XOutputStream > &xOutput) override
Definition: scriptcont.cxx:149
virtual void onNewRootStorage() override
virtual OUString SAL_CALL getImplementationName() override
virtual sal_Bool SAL_CALL HasExecutableCode(const OUString &) override
virtual sal_Bool SAL_CALL isLibraryPasswordVerified(const OUString &Name) override
Definition: scriptcont.cxx:360
SfxScriptLibrary(ModifiableHelper &_rModifiable, const css::uno::Reference< css::ucb::XSimpleFileAccess3 > &xSFI)
virtual bool isLibraryElementValid(const css::uno::Any &rElement) const override
virtual void storeResources() override
virtual sal_Bool SAL_CALL hasModuleInfo(const OUString &ModuleName) override
virtual void SAL_CALL removeModuleInfo(const OUString &ModuleName) override
virtual css::script::ModuleInfo SAL_CALL getModuleInfo(const OUString &ModuleName) override
virtual void storeResourcesToStorage(const css::uno::Reference< css::embed::XStorage > &xStorage) override
virtual void SAL_CALL insertModuleInfo(const OUString &ModuleName, const css::script::ModuleInfo &ModuleInfo) override
virtual bool isLoadedStorable() override
virtual void storeResourcesToURL(const OUString &URL, const css::uno::Reference< css::task::XInteractionHandler > &xHandler) override
static bool containsValidModule(const css::uno::Any &_rElement)
virtual void storeResourcesAsURL(const OUString &URL, const OUString &NewName) override
virtual bool isModified() override
ModuleInfoMap mModuleInfo
Definition: scriptcont.hxx:117
static css::uno::Reference< css::embed::XStorage > GetStorageFromURL(const OUString &aURL, sal_Int32 nStorageMode, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
float u
#define ERRCODE_IO_GENERAL
#define ERRCODE_NONE
Reference< XSingleServiceFactory > xFactory
const char * pLib
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
IMPLEMENT_FORWARD_XTYPEPROVIDER2(SfxDialogLibrary, SfxLibrary, SfxDialogLibrary_BASE)
IMPLEMENT_FORWARD_XINTERFACE2(SfxDialogLibrary, SfxLibrary, SfxDialogLibrary_BASE)
static void setStreamKey(const uno::Reference< io::XStream > &xStream, const OUString &aPass)
Definition: scriptcont.cxx:537
@ Exception
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
void exportScriptModule(Reference< xml::sax::XWriter > const &xOut, const ModuleDescriptor &rMod)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_sfx2_ScriptLibraryContainer_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
#define ERRCTX_SFX_LOADBASIC
Reference< XModel > xModel
@ WRITE
Definition: token.hxx:64
@ READ
Definition: token.hxx:80
OUString Name
unsigned char sal_Bool
signed char sal_Int8
OUString aTargetURL