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 <vcl/errinf.hxx> 21 #include <tools/stream.hxx> 22 #include <sot/storage.hxx> 23 #include <tools/urlobj.hxx> 24 #include <svl/hint.hxx> 25 #include <vcl/svapp.hxx> 26 #include <vcl/window.hxx> 27 #include <vcl/wrkwin.hxx> 28 #include <basic/sbx.hxx> 29 #include <sot/storinfo.hxx> 30 #include <unotools/pathoptions.hxx> 31 #include <tools/debug.hxx> 32 #include <tools/diagnose_ex.h> 33 #include <basic/sbmod.hxx> 34 #include <unotools/intlwrapper.hxx> 35 #include <sal/log.hxx> 36 37 #include <basic/sbuno.hxx> 38 #include <basic/basmgr.hxx> 39 #include <global.hxx> 40 #include <sbunoobj.hxx> 41 #include <sbintern.hxx> 42 #include <com/sun/star/script/XLibraryContainer.hpp> 43 #include <com/sun/star/script/XPersistentLibraryContainer.hpp> 44 45 #include <memory> 46 #include <vector> 47 48 #define LIB_SEP 0x01 49 #define LIBINFO_SEP 0x02 50 #define LIBINFO_ID 0x1491 51 #define PASSWORD_MARKER 0x31452134 52 53 54 // Library API, implemented for XML import/export 55 56 #include <com/sun/star/container/XNameContainer.hpp> 57 #include <com/sun/star/container/XContainer.hpp> 58 #include <com/sun/star/script/XStarBasicAccess.hpp> 59 #include <com/sun/star/script/XStarBasicModuleInfo.hpp> 60 #include <com/sun/star/script/XStarBasicDialogInfo.hpp> 61 #include <com/sun/star/script/XStarBasicLibraryInfo.hpp> 62 #include <com/sun/star/script/XLibraryContainerPassword.hpp> 63 #include <com/sun/star/script/ModuleInfo.hpp> 64 #include <com/sun/star/script/vba/XVBACompatibility.hpp> 65 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp> 66 #include <com/sun/star/ucb/ContentCreationException.hpp> 67 68 #include <cppuhelper/implbase.hxx> 69 70 using com::sun::star::uno::Reference; 71 using namespace com::sun::star; 72 using namespace com::sun::star::script; 73 using namespace cppu; 74 75 typedef WeakImplHelper< container::XNameContainer > NameContainerHelper; 76 typedef WeakImplHelper< script::XStarBasicModuleInfo > ModuleInfoHelper; 77 typedef WeakImplHelper< script::XStarBasicAccess > StarBasicAccessHelper; 78 79 // Version 1 80 // sal_uInt32 nEndPos 81 // sal_uInt16 nId 82 // sal_uInt16 nVer 83 // bool bDoLoad 84 // String LibName 85 // String AbsStorageName 86 // String RelStorageName 87 // Version 2 88 // + bool bReference 89 90 static const char szStdLibName[] = "Standard"; 91 static const char szBasicStorage[] = "StarBASIC"; 92 static const char szOldManagerStream[] = "BasicManager"; 93 static const char szManagerStream[] = "BasicManager2"; 94 static const char szImbedded[] = "LIBIMBEDDED"; 95 static const char szCryptingKey[] = "CryptedBasic"; 96 97 98 const StreamMode eStreamReadMode = StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL; 99 const StreamMode eStorageReadMode = StreamMode::READ | StreamMode::SHARE_DENYWRITE; 100 101 102 // BasicManager impl data 103 struct BasicManagerImpl 104 { 105 LibraryContainerInfo maContainerInfo; 106 107 std::vector<std::unique_ptr<BasicLibInfo>> aLibs; 108 OUString aBasicLibPath; 109 110 BasicManagerImpl() 111 {} 112 }; 113 114 // BasMgrContainerListenerImpl 115 116 117 typedef ::cppu::WeakImplHelper< container::XContainerListener > ContainerListenerHelper; 118 119 class BasMgrContainerListenerImpl: public ContainerListenerHelper 120 { 121 BasicManager* mpMgr; 122 OUString maLibName; // empty -> no lib, but lib container 123 124 public: 125 BasMgrContainerListenerImpl( BasicManager* pMgr, const OUString& aLibName ) 126 : mpMgr( pMgr ) 127 , maLibName( aLibName ) {} 128 129 static void insertLibraryImpl( const uno::Reference< script::XLibraryContainer >& xScriptCont, BasicManager* pMgr, 130 const uno::Any& aLibAny, const OUString& aLibName ); 131 static void addLibraryModulesImpl( BasicManager const * pMgr, const uno::Reference< container::XNameAccess >& xLibNameAccess, 132 const OUString& aLibName ); 133 134 135 // XEventListener 136 virtual void SAL_CALL disposing( const lang::EventObject& Source ) override; 137 138 // XContainerListener 139 virtual void SAL_CALL elementInserted( const container::ContainerEvent& Event ) override; 140 virtual void SAL_CALL elementReplaced( const container::ContainerEvent& Event ) override; 141 virtual void SAL_CALL elementRemoved( const container::ContainerEvent& Event ) override; 142 }; 143 144 145 // BasMgrContainerListenerImpl 146 147 148 void BasMgrContainerListenerImpl::insertLibraryImpl( const uno::Reference< script::XLibraryContainer >& xScriptCont, 149 BasicManager* pMgr, const uno::Any& aLibAny, const OUString& aLibName ) 150 { 151 Reference< container::XNameAccess > xLibNameAccess; 152 aLibAny >>= xLibNameAccess; 153 154 if( !pMgr->GetLib( aLibName ) ) 155 { 156 StarBASIC* pLib = 157 pMgr->CreateLibForLibContainer( aLibName, xScriptCont ); 158 DBG_ASSERT( pLib, "XML Import: Basic library could not be created"); 159 } 160 161 uno::Reference< container::XContainer> xLibContainer( xLibNameAccess, uno::UNO_QUERY ); 162 if( xLibContainer.is() ) 163 { 164 // Register listener for library 165 Reference< container::XContainerListener > xLibraryListener 166 = new BasMgrContainerListenerImpl( pMgr, aLibName ); 167 xLibContainer->addContainerListener( xLibraryListener ); 168 } 169 170 if( xScriptCont->isLibraryLoaded( aLibName ) ) 171 { 172 addLibraryModulesImpl( pMgr, xLibNameAccess, aLibName ); 173 } 174 } 175 176 177 void BasMgrContainerListenerImpl::addLibraryModulesImpl( BasicManager const * pMgr, 178 const uno::Reference< container::XNameAccess >& xLibNameAccess, const OUString& aLibName ) 179 { 180 uno::Sequence< OUString > aModuleNames = xLibNameAccess->getElementNames(); 181 sal_Int32 nModuleCount = aModuleNames.getLength(); 182 183 StarBASIC* pLib = pMgr->GetLib( aLibName ); 184 DBG_ASSERT( pLib, "BasMgrContainerListenerImpl::addLibraryModulesImpl: Unknown lib!"); 185 if( pLib ) 186 { 187 const OUString* pNames = aModuleNames.getConstArray(); 188 for( sal_Int32 j = 0 ; j < nModuleCount ; j++ ) 189 { 190 OUString aModuleName = pNames[ j ]; 191 uno::Any aElement = xLibNameAccess->getByName( aModuleName ); 192 OUString aMod; 193 aElement >>= aMod; 194 uno::Reference< vba::XVBAModuleInfo > xVBAModuleInfo( xLibNameAccess, uno::UNO_QUERY ); 195 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( aModuleName ) ) 196 { 197 ModuleInfo aInfo = xVBAModuleInfo->getModuleInfo( aModuleName ); 198 pLib->MakeModule( aModuleName, aInfo, aMod ); 199 } 200 else 201 pLib->MakeModule( aModuleName, aMod ); 202 } 203 204 pLib->SetModified( false ); 205 } 206 } 207 208 209 // XEventListener 210 211 212 void SAL_CALL BasMgrContainerListenerImpl::disposing( const lang::EventObject& ) {} 213 214 // XContainerListener 215 216 217 void SAL_CALL BasMgrContainerListenerImpl::elementInserted( const container::ContainerEvent& Event ) 218 { 219 bool bLibContainer = maLibName.isEmpty(); 220 OUString aName; 221 Event.Accessor >>= aName; 222 223 if( bLibContainer ) 224 { 225 uno::Reference< script::XLibraryContainer > xScriptCont( Event.Source, uno::UNO_QUERY ); 226 if (xScriptCont.is()) 227 insertLibraryImpl(xScriptCont, mpMgr, Event.Element, aName); 228 StarBASIC* pLib = mpMgr->GetLib( aName ); 229 if ( pLib ) 230 { 231 uno::Reference< vba::XVBACompatibility > xVBACompat( xScriptCont, uno::UNO_QUERY ); 232 if ( xVBACompat.is() ) 233 pLib->SetVBAEnabled( xVBACompat->getVBACompatibilityMode() ); 234 } 235 } 236 else 237 { 238 239 StarBASIC* pLib = mpMgr->GetLib( maLibName ); 240 DBG_ASSERT( pLib, "BasMgrContainerListenerImpl::elementInserted: Unknown lib!"); 241 if( pLib ) 242 { 243 SbModule* pMod = pLib->FindModule( aName ); 244 if( !pMod ) 245 { 246 OUString aMod; 247 Event.Element >>= aMod; 248 uno::Reference< vba::XVBAModuleInfo > xVBAModuleInfo( Event.Source, uno::UNO_QUERY ); 249 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( aName ) ) 250 { 251 ModuleInfo aInfo = xVBAModuleInfo->getModuleInfo( aName ); 252 pLib->MakeModule( aName, aInfo, aMod ); 253 } 254 else 255 pLib->MakeModule( aName, aMod ); 256 pLib->SetModified( false ); 257 } 258 } 259 } 260 } 261 262 263 void SAL_CALL BasMgrContainerListenerImpl::elementReplaced( const container::ContainerEvent& Event ) 264 { 265 OUString aName; 266 Event.Accessor >>= aName; 267 268 // Replace not possible for library container 269 DBG_ASSERT( !maLibName.isEmpty(), "library container fired elementReplaced()"); 270 271 StarBASIC* pLib = mpMgr->GetLib( maLibName ); 272 if( pLib ) 273 { 274 SbModule* pMod = pLib->FindModule( aName ); 275 OUString aMod; 276 Event.Element >>= aMod; 277 278 if( pMod ) 279 pMod->SetSource32( aMod ); 280 else 281 pLib->MakeModule( aName, aMod ); 282 283 pLib->SetModified( false ); 284 } 285 } 286 287 288 void SAL_CALL BasMgrContainerListenerImpl::elementRemoved( const container::ContainerEvent& Event ) 289 { 290 OUString aName; 291 Event.Accessor >>= aName; 292 293 bool bLibContainer = maLibName.isEmpty(); 294 if( bLibContainer ) 295 { 296 StarBASIC* pLib = mpMgr->GetLib( aName ); 297 if( pLib ) 298 { 299 sal_uInt16 nLibId = mpMgr->GetLibId( aName ); 300 mpMgr->RemoveLib( nLibId, false ); 301 } 302 } 303 else 304 { 305 StarBASIC* pLib = mpMgr->GetLib( maLibName ); 306 SbModule* pMod = pLib ? pLib->FindModule( aName ) : nullptr; 307 if( pMod ) 308 { 309 pLib->Remove( pMod ); 310 pLib->SetModified( false ); 311 } 312 } 313 } 314 315 BasicError::BasicError( ErrCode nId, BasicErrorReason nR ) 316 { 317 nErrorId = nId; 318 nReason = nR; 319 } 320 321 BasicError::BasicError( const BasicError& rErr ) 322 { 323 nErrorId = rErr.nErrorId; 324 nReason = rErr.nReason; 325 } 326 327 328 class BasicLibInfo 329 { 330 private: 331 StarBASICRef xLib; 332 OUString aLibName; 333 OUString aStorageName; // string is sufficient, unique at runtime 334 OUString aRelStorageName; 335 OUString aPassword; 336 337 bool bDoLoad; 338 bool bReference; 339 340 // Lib represents library in new UNO library container 341 uno::Reference< script::XLibraryContainer > mxScriptCont; 342 343 public: 344 BasicLibInfo(); 345 346 bool IsReference() const { return bReference; } 347 void SetReference(bool b) { bReference = b; } 348 349 bool IsExtern() const { return aStorageName != szImbedded; } 350 351 void SetStorageName( const OUString& rName ) { aStorageName = rName; } 352 const OUString& GetStorageName() const { return aStorageName; } 353 354 void SetRelStorageName( const OUString& rN ) { aRelStorageName = rN; } 355 const OUString& GetRelStorageName() const { return aRelStorageName; } 356 357 StarBASICRef GetLib() const 358 { 359 if( mxScriptCont.is() && mxScriptCont->hasByName( aLibName ) && 360 !mxScriptCont->isLibraryLoaded( aLibName ) ) 361 return StarBASICRef(); 362 return xLib; 363 } 364 StarBASICRef& GetLibRef() { return xLib; } 365 void SetLib( StarBASIC* pBasic ) { xLib = pBasic; } 366 367 const OUString& GetLibName() const { return aLibName; } 368 void SetLibName( const OUString& rName ) { aLibName = rName; } 369 370 // Only temporary for Load/Save 371 bool DoLoad() { return bDoLoad; } 372 373 bool HasPassword() const { return !aPassword.isEmpty(); } 374 const OUString& GetPassword() const { return aPassword; } 375 void SetPassword( const OUString& rNewPassword ) 376 { aPassword = rNewPassword; } 377 378 static BasicLibInfo* Create( SotStorageStream& rSStream ); 379 380 const uno::Reference< script::XLibraryContainer >& GetLibraryContainer() 381 { return mxScriptCont; } 382 void SetLibraryContainer( const uno::Reference< script::XLibraryContainer >& xScriptCont ) 383 { mxScriptCont = xScriptCont; } 384 }; 385 386 387 BasicLibInfo::BasicLibInfo() 388 : aStorageName(szImbedded) 389 , aRelStorageName(szImbedded) 390 , bDoLoad(false) 391 , bReference(false) 392 { 393 } 394 395 BasicLibInfo* BasicLibInfo::Create( SotStorageStream& rSStream ) 396 { 397 BasicLibInfo* pInfo = new BasicLibInfo; 398 399 sal_uInt32 nEndPos; 400 sal_uInt16 nId; 401 sal_uInt16 nVer; 402 403 rSStream.ReadUInt32( nEndPos ); 404 rSStream.ReadUInt16( nId ); 405 rSStream.ReadUInt16( nVer ); 406 407 DBG_ASSERT( nId == LIBINFO_ID, "No BasicLibInfo?!" ); 408 if( nId == LIBINFO_ID ) 409 { 410 // Reload? 411 bool bDoLoad; 412 rSStream.ReadCharAsBool( bDoLoad ); 413 pInfo->bDoLoad = bDoLoad; 414 415 // The name of the lib... 416 OUString aName = rSStream.ReadUniOrByteString(rSStream.GetStreamCharSet()); 417 pInfo->SetLibName( aName ); 418 419 // Absolute path... 420 OUString aStorageName = rSStream.ReadUniOrByteString(rSStream.GetStreamCharSet()); 421 pInfo->SetStorageName( aStorageName ); 422 423 // Relative path... 424 OUString aRelStorageName = rSStream.ReadUniOrByteString(rSStream.GetStreamCharSet()); 425 pInfo->SetRelStorageName( aRelStorageName ); 426 427 if ( nVer >= 2 ) 428 { 429 bool bReferenz; 430 rSStream.ReadCharAsBool( bReferenz ); 431 pInfo->SetReference(bReferenz); 432 } 433 434 rSStream.Seek( nEndPos ); 435 } 436 return pInfo; 437 } 438 439 BasicManager::BasicManager( SotStorage& rStorage, const OUString& rBaseURL, StarBASIC* pParentFromStdLib, OUString const * pLibPath, bool bDocMgr ) : mbDocMgr( bDocMgr ) 440 { 441 Init(); 442 443 if( pLibPath ) 444 { 445 mpImpl->aBasicLibPath = *pLibPath; 446 } 447 OUString aStorName( rStorage.GetName() ); 448 maStorageName = INetURLObject(aStorName, INetProtocol::File).GetMainURL( INetURLObject::DecodeMechanism::NONE ); 449 450 451 // If there is no Manager Stream, no further actions are necessary 452 if ( rStorage.IsStream( szManagerStream ) ) 453 { 454 LoadBasicManager( rStorage, rBaseURL ); 455 // StdLib contains Parent: 456 StarBASIC* pStdLib = GetStdLib(); 457 DBG_ASSERT( pStdLib, "Standard-Lib not loaded?" ); 458 if ( !pStdLib ) 459 { 460 // Should never happen, but if it happens we won't crash... 461 pStdLib = new StarBASIC( nullptr, mbDocMgr ); 462 463 if (mpImpl->aLibs.empty()) 464 CreateLibInfo(); 465 466 BasicLibInfo& rStdLibInfo = *mpImpl->aLibs.front(); 467 468 rStdLibInfo.SetLib( pStdLib ); 469 StarBASICRef xStdLib = rStdLibInfo.GetLib(); 470 xStdLib->SetName( szStdLibName ); 471 rStdLibInfo.SetLibName( szStdLibName ); 472 xStdLib->SetFlag( SbxFlagBits::DontStore | SbxFlagBits::ExtSearch ); 473 xStdLib->SetModified( false ); 474 } 475 else 476 { 477 pStdLib->SetParent( pParentFromStdLib ); 478 // The other get StdLib as parent: 479 480 for ( sal_uInt16 nBasic = 1; nBasic < GetLibCount(); nBasic++ ) 481 { 482 StarBASIC* pBasic = GetLib( nBasic ); 483 if ( pBasic ) 484 { 485 pStdLib->Insert( pBasic ); 486 pBasic->SetFlag( SbxFlagBits::ExtSearch ); 487 } 488 } 489 // Modified through insert 490 pStdLib->SetModified( false ); 491 } 492 } 493 else 494 { 495 ImpCreateStdLib( pParentFromStdLib ); 496 if ( rStorage.IsStream( szOldManagerStream ) ) 497 LoadOldBasicManager( rStorage ); 498 } 499 } 500 501 static void copyToLibraryContainer( StarBASIC* pBasic, const LibraryContainerInfo& rInfo ) 502 { 503 uno::Reference< script::XLibraryContainer > xScriptCont( rInfo.mxScriptCont.get() ); 504 if ( !xScriptCont.is() ) 505 return; 506 507 OUString aLibName = pBasic->GetName(); 508 if( !xScriptCont->hasByName( aLibName ) ) 509 xScriptCont->createLibrary( aLibName ); 510 511 uno::Any aLibAny = xScriptCont->getByName( aLibName ); 512 uno::Reference< container::XNameContainer > xLib; 513 aLibAny >>= xLib; 514 if ( !xLib.is() ) 515 return; 516 517 for ( const auto& pModule: pBasic->GetModules() ) 518 { 519 OUString aModName = pModule->GetName(); 520 if( !xLib->hasByName( aModName ) ) 521 { 522 OUString aSource = pModule->GetSource32(); 523 uno::Any aSourceAny; 524 aSourceAny <<= aSource; 525 xLib->insertByName( aModName, aSourceAny ); 526 } 527 } 528 } 529 530 const uno::Reference< script::XPersistentLibraryContainer >& BasicManager::GetDialogLibraryContainer() const 531 { 532 return mpImpl->maContainerInfo.mxDialogCont; 533 } 534 535 const uno::Reference< script::XPersistentLibraryContainer >& BasicManager::GetScriptLibraryContainer() const 536 { 537 return mpImpl->maContainerInfo.mxScriptCont; 538 } 539 540 void BasicManager::SetLibraryContainerInfo( const LibraryContainerInfo& rInfo ) 541 { 542 mpImpl->maContainerInfo = rInfo; 543 544 uno::Reference< script::XLibraryContainer > xScriptCont( mpImpl->maContainerInfo.mxScriptCont.get() ); 545 if( xScriptCont.is() ) 546 { 547 // Register listener for lib container 548 uno::Reference< container::XContainerListener > xLibContainerListener 549 = new BasMgrContainerListenerImpl( this, "" ); 550 551 uno::Reference< container::XContainer> xLibContainer( xScriptCont, uno::UNO_QUERY ); 552 xLibContainer->addContainerListener( xLibContainerListener ); 553 554 uno::Sequence< OUString > aScriptLibNames = xScriptCont->getElementNames(); 555 556 if( aScriptLibNames.hasElements() ) 557 { 558 for(const auto& rScriptLibName : aScriptLibNames) 559 { 560 uno::Any aLibAny = xScriptCont->getByName( rScriptLibName ); 561 562 if ( rScriptLibName == "Standard" || rScriptLibName == "VBAProject") 563 xScriptCont->loadLibrary( rScriptLibName ); 564 565 BasMgrContainerListenerImpl::insertLibraryImpl 566 ( xScriptCont, this, aLibAny, rScriptLibName ); 567 } 568 } 569 else 570 { 571 // No libs? Maybe an 5.2 document already loaded 572 for (auto const& rpBasLibInfo : mpImpl->aLibs) 573 { 574 StarBASIC* pLib = rpBasLibInfo->GetLib().get(); 575 if( !pLib ) 576 { 577 bool bLoaded = ImpLoadLibrary( rpBasLibInfo.get(), nullptr ); 578 if( bLoaded ) 579 pLib = rpBasLibInfo->GetLib().get(); 580 } 581 if( pLib ) 582 { 583 copyToLibraryContainer( pLib, mpImpl->maContainerInfo ); 584 if (rpBasLibInfo->HasPassword()) 585 { 586 OldBasicPassword* pOldBasicPassword = 587 mpImpl->maContainerInfo.mpOldBasicPassword; 588 if( pOldBasicPassword ) 589 { 590 pOldBasicPassword->setLibraryPassword( 591 pLib->GetName(), rpBasLibInfo->GetPassword() ); 592 } 593 } 594 } 595 } 596 } 597 } 598 599 SetGlobalUNOConstant( "BasicLibraries", uno::Any( mpImpl->maContainerInfo.mxScriptCont ) ); 600 SetGlobalUNOConstant( "DialogLibraries", uno::Any( mpImpl->maContainerInfo.mxDialogCont ) ); 601 } 602 603 BasicManager::BasicManager( StarBASIC* pSLib, OUString const * pLibPath, bool bDocMgr ) : mbDocMgr( bDocMgr ) 604 { 605 Init(); 606 DBG_ASSERT( pSLib, "BasicManager cannot be created with a NULL-Pointer!" ); 607 608 if( pLibPath ) 609 { 610 mpImpl->aBasicLibPath = *pLibPath; 611 } 612 BasicLibInfo* pStdLibInfo = CreateLibInfo(); 613 pStdLibInfo->SetLib( pSLib ); 614 StarBASICRef xStdLib = pStdLibInfo->GetLib(); 615 xStdLib->SetName(szStdLibName); 616 pStdLibInfo->SetLibName(szStdLibName ); 617 pSLib->SetFlag( SbxFlagBits::DontStore | SbxFlagBits::ExtSearch ); 618 619 // Save is only necessary if basic has changed 620 xStdLib->SetModified( false ); 621 } 622 623 void BasicManager::ImpMgrNotLoaded( const OUString& rStorageName ) 624 { 625 // pErrInf is only destroyed if the error os processed by an 626 // ErrorHandler 627 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, rStorageName, DialogMask::ButtonsOk ); 628 aErrors.emplace_back(*pErrInf, BasicErrorReason::OPENMGRSTREAM); 629 630 // Create a stdlib otherwise we crash! 631 BasicLibInfo* pStdLibInfo = CreateLibInfo(); 632 pStdLibInfo->SetLib( new StarBASIC( nullptr, mbDocMgr ) ); 633 StarBASICRef xStdLib = pStdLibInfo->GetLib(); 634 xStdLib->SetName( szStdLibName ); 635 pStdLibInfo->SetLibName( szStdLibName ); 636 xStdLib->SetFlag( SbxFlagBits::DontStore | SbxFlagBits::ExtSearch ); 637 xStdLib->SetModified( false ); 638 } 639 640 641 void BasicManager::ImpCreateStdLib( StarBASIC* pParentFromStdLib ) 642 { 643 BasicLibInfo* pStdLibInfo = CreateLibInfo(); 644 StarBASIC* pStdLib = new StarBASIC( pParentFromStdLib, mbDocMgr ); 645 pStdLibInfo->SetLib( pStdLib ); 646 pStdLib->SetName( szStdLibName ); 647 pStdLibInfo->SetLibName( szStdLibName ); 648 pStdLib->SetFlag( SbxFlagBits::DontStore | SbxFlagBits::ExtSearch ); 649 } 650 651 void BasicManager::LoadBasicManager( SotStorage& rStorage, const OUString& rBaseURL ) 652 { 653 tools::SvRef<SotStorageStream> xManagerStream = rStorage.OpenSotStream( szManagerStream, eStreamReadMode ); 654 655 OUString aStorName( rStorage.GetName() ); 656 // #i13114 removed, DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); 657 658 if ( !xManagerStream.is() || xManagerStream->GetError() || ( xManagerStream->TellEnd() == 0 ) ) 659 { 660 ImpMgrNotLoaded( aStorName ); 661 return; 662 } 663 664 maStorageName = INetURLObject(aStorName, INetProtocol::File).GetMainURL( INetURLObject::DecodeMechanism::NONE ); 665 // #i13114 removed, DBG_ASSERT(aStorageName.Len() != 0, "Bad storage name"); 666 667 OUString aRealStorageName = maStorageName; // for relative paths, can be modified through BaseURL 668 669 if ( !rBaseURL.isEmpty() ) 670 { 671 INetURLObject aObj( rBaseURL ); 672 if ( aObj.GetProtocol() == INetProtocol::File ) 673 { 674 aRealStorageName = aObj.PathToFileName(); 675 } 676 } 677 678 xManagerStream->SetBufferSize( 1024 ); 679 xManagerStream->Seek( STREAM_SEEK_TO_BEGIN ); 680 681 sal_uInt32 nEndPos; 682 xManagerStream->ReadUInt32( nEndPos ); 683 684 sal_uInt16 nLibs; 685 xManagerStream->ReadUInt16( nLibs ); 686 // Plausibility! 687 if( nLibs & 0xF000 ) 688 { 689 SAL_WARN( "basic", "BasicManager-Stream defect!" ); 690 return; 691 } 692 const size_t nMinBasicLibSize(8); 693 const size_t nMaxPossibleLibs = xManagerStream->remainingSize() / nMinBasicLibSize; 694 if (nLibs > nMaxPossibleLibs) 695 { 696 SAL_WARN("basic", "Parsing error: " << nMaxPossibleLibs << 697 " max possible entries, but " << nLibs << " claimed, truncating"); 698 nLibs = nMaxPossibleLibs; 699 } 700 for (sal_uInt16 nL = 0; nL < nLibs; ++nL) 701 { 702 BasicLibInfo* pInfo = BasicLibInfo::Create( *xManagerStream ); 703 704 // Correct absolute pathname if relative is existing. 705 // Always try relative first if there are two stands on disk 706 if ( !pInfo->GetRelStorageName().isEmpty() && pInfo->GetRelStorageName() != szImbedded ) 707 { 708 INetURLObject aObj( aRealStorageName, INetProtocol::File ); 709 aObj.removeSegment(); 710 bool bWasAbsolute = false; 711 aObj = aObj.smartRel2Abs( pInfo->GetRelStorageName(), bWasAbsolute ); 712 713 //*** TODO: Replace if still necessary 714 //*** TODO-End 715 if ( ! mpImpl->aBasicLibPath.isEmpty() ) 716 { 717 // Search lib in path 718 OUString aSearchFile = pInfo->GetRelStorageName(); 719 OUString aSearchFileOldFormat(aSearchFile); 720 SvtPathOptions aPathCFG; 721 if( aPathCFG.SearchFile( aSearchFileOldFormat, SvtPathOptions::PATH_BASIC ) ) 722 { 723 pInfo->SetStorageName( aSearchFile ); 724 } 725 } 726 } 727 728 mpImpl->aLibs.push_back(std::unique_ptr<BasicLibInfo>(pInfo)); 729 // Libs from external files should be loaded only when necessary. 730 // But references are loaded at once, otherwise some big customers get into trouble 731 if ( pInfo->DoLoad() && 732 ( !pInfo->IsExtern() || pInfo->IsReference())) 733 { 734 ImpLoadLibrary( pInfo, &rStorage ); 735 } 736 } 737 738 xManagerStream->Seek( nEndPos ); 739 xManagerStream->SetBufferSize( 0 ); 740 xManagerStream.clear(); 741 } 742 743 void BasicManager::LoadOldBasicManager( SotStorage& rStorage ) 744 { 745 tools::SvRef<SotStorageStream> xManagerStream = rStorage.OpenSotStream( szOldManagerStream, eStreamReadMode ); 746 747 OUString aStorName( rStorage.GetName() ); 748 DBG_ASSERT( aStorName.getLength(), "No Storage Name!" ); 749 750 if ( !xManagerStream.is() || xManagerStream->GetError() || ( xManagerStream->TellEnd() == 0 ) ) 751 { 752 ImpMgrNotLoaded( aStorName ); 753 return; 754 } 755 756 xManagerStream->SetBufferSize( 1024 ); 757 xManagerStream->Seek( STREAM_SEEK_TO_BEGIN ); 758 sal_uInt32 nBasicStartOff, nBasicEndOff; 759 xManagerStream->ReadUInt32( nBasicStartOff ); 760 xManagerStream->ReadUInt32( nBasicEndOff ); 761 762 DBG_ASSERT( !xManagerStream->GetError(), "Invalid Manager-Stream!" ); 763 764 xManagerStream->Seek( nBasicStartOff ); 765 if (!ImplLoadBasic( *xManagerStream, mpImpl->aLibs.front()->GetLibRef() )) 766 { 767 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, aStorName, DialogMask::ButtonsOk ); 768 aErrors.emplace_back(*pErrInf, BasicErrorReason::OPENMGRSTREAM); 769 // and it proceeds ... 770 } 771 xManagerStream->Seek( nBasicEndOff+1 ); // +1: 0x00 as separator 772 OUString aLibs = xManagerStream->ReadUniOrByteString(xManagerStream->GetStreamCharSet()); 773 xManagerStream->SetBufferSize( 0 ); 774 xManagerStream.clear(); // Close stream 775 776 if ( !aLibs.isEmpty() ) 777 { 778 INetURLObject aCurStorage( aStorName, INetProtocol::File ); 779 sal_Int32 nLibPos {0}; 780 do { 781 const OUString aLibInfo(aLibs.getToken(0, LIB_SEP, nLibPos)); 782 sal_Int32 nInfoPos {0}; 783 const OUString aLibName( aLibInfo.getToken( 0, LIBINFO_SEP, nInfoPos ) ); 784 DBG_ASSERT( nInfoPos >= 0, "Invalid Lib-Info!" ); 785 const OUString aLibAbsStorageName( aLibInfo.getToken( 0, LIBINFO_SEP, nInfoPos ) ); 786 // TODO: fail also here if there are no more tokens? 787 const OUString aLibRelStorageName( aLibInfo.getToken( 0, LIBINFO_SEP, nInfoPos ) ); 788 DBG_ASSERT( nInfoPos < 0, "Invalid Lib-Info!" ); 789 INetURLObject aLibAbsStorage( aLibAbsStorageName, INetProtocol::File ); 790 791 INetURLObject aLibRelStorage( aStorName ); 792 aLibRelStorage.removeSegment(); 793 bool bWasAbsolute = false; 794 aLibRelStorage = aLibRelStorage.smartRel2Abs( aLibRelStorageName, bWasAbsolute); 795 DBG_ASSERT(!bWasAbsolute, "RelStorageName was absolute!" ); 796 797 tools::SvRef<SotStorage> xStorageRef; 798 if ( aLibAbsStorage == aCurStorage || aLibRelStorageName == szImbedded ) 799 { 800 xStorageRef = &rStorage; 801 } 802 else 803 { 804 xStorageRef = new SotStorage( false, aLibAbsStorage.GetMainURL 805 ( INetURLObject::DecodeMechanism::NONE ), eStorageReadMode ); 806 if ( xStorageRef->GetError() != ERRCODE_NONE ) 807 xStorageRef = new SotStorage( false, aLibRelStorage. 808 GetMainURL( INetURLObject::DecodeMechanism::NONE ), eStorageReadMode ); 809 } 810 if ( xStorageRef.is() ) 811 { 812 AddLib( *xStorageRef, aLibName, false ); 813 } 814 else 815 { 816 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD, aStorName, DialogMask::ButtonsOk ); 817 aErrors.emplace_back(*pErrInf, BasicErrorReason::STORAGENOTFOUND); 818 } 819 } while (nLibPos>=0); 820 } 821 } 822 823 BasicManager::~BasicManager() 824 { 825 // Notify listener if something needs to be saved 826 Broadcast( SfxHint( SfxHintId::Dying) ); 827 } 828 829 bool BasicManager::HasExeCode( const OUString& sLib ) 830 { 831 StarBASIC* pLib = GetLib(sLib); 832 if ( pLib ) 833 { 834 for (const auto& pModule: pLib->GetModules()) 835 { 836 if (pModule->HasExeCode()) 837 return true; 838 } 839 } 840 return false; 841 } 842 843 void BasicManager::Init() 844 { 845 mpImpl.reset( new BasicManagerImpl ); 846 } 847 848 BasicLibInfo* BasicManager::CreateLibInfo() 849 { 850 BasicLibInfo* pInf(new BasicLibInfo); 851 mpImpl->aLibs.push_back(std::unique_ptr<BasicLibInfo>(pInf)); 852 return pInf; 853 } 854 855 bool BasicManager::ImpLoadLibrary( BasicLibInfo* pLibInfo, SotStorage* pCurStorage ) 856 { 857 try { 858 DBG_ASSERT( pLibInfo, "LibInfo!?" ); 859 860 OUString aStorageName( pLibInfo->GetStorageName() ); 861 if ( aStorageName.isEmpty() || aStorageName == szImbedded ) 862 { 863 aStorageName = GetStorageName(); 864 } 865 tools::SvRef<SotStorage> xStorage; 866 // The current must not be opened again... 867 if ( pCurStorage ) 868 { 869 OUString aStorName( pCurStorage->GetName() ); 870 // #i13114 removed, DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); 871 872 INetURLObject aCurStorageEntry(aStorName, INetProtocol::File); 873 // #i13114 removed, DBG_ASSERT(aCurStorageEntry.GetMainURL( INetURLObject::DecodeMechanism::NONE ).Len() != 0, "Bad storage name"); 874 875 INetURLObject aStorageEntry(aStorageName, INetProtocol::File); 876 // #i13114 removed, DBG_ASSERT(aCurStorageEntry.GetMainURL( INetURLObject::DecodeMechanism::NONE ).Len() != 0, "Bad storage name"); 877 878 if ( aCurStorageEntry == aStorageEntry ) 879 { 880 xStorage = pCurStorage; 881 } 882 } 883 884 if ( !xStorage.is() ) 885 { 886 xStorage = new SotStorage( false, aStorageName, eStorageReadMode ); 887 } 888 tools::SvRef<SotStorage> xBasicStorage = xStorage->OpenSotStorage( szBasicStorage, eStorageReadMode, false ); 889 890 if ( !xBasicStorage.is() || xBasicStorage->GetError() ) 891 { 892 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, xStorage->GetName(), DialogMask::ButtonsOk ); 893 aErrors.emplace_back(*pErrInf, BasicErrorReason::OPENLIBSTORAGE); 894 } 895 else 896 { 897 // In the Basic-Storage every lib is in a Stream... 898 tools::SvRef<SotStorageStream> xBasicStream = xBasicStorage->OpenSotStream( pLibInfo->GetLibName(), eStreamReadMode ); 899 if ( !xBasicStream.is() || xBasicStream->GetError() ) 900 { 901 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD , pLibInfo->GetLibName(), DialogMask::ButtonsOk ); 902 aErrors.emplace_back(*pErrInf, BasicErrorReason::OPENLIBSTREAM); 903 } 904 else 905 { 906 bool bLoaded = false; 907 if ( xBasicStream->TellEnd() != 0 ) 908 { 909 if ( !pLibInfo->GetLib().is() ) 910 { 911 pLibInfo->SetLib( new StarBASIC( GetStdLib(), mbDocMgr ) ); 912 } 913 xBasicStream->SetBufferSize( 1024 ); 914 xBasicStream->Seek( STREAM_SEEK_TO_BEGIN ); 915 bLoaded = ImplLoadBasic( *xBasicStream, pLibInfo->GetLibRef() ); 916 xBasicStream->SetBufferSize( 0 ); 917 StarBASICRef xStdLib = pLibInfo->GetLib(); 918 xStdLib->SetName( pLibInfo->GetLibName() ); 919 xStdLib->SetModified( false ); 920 xStdLib->SetFlag( SbxFlagBits::DontStore ); 921 } 922 if ( !bLoaded ) 923 { 924 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD, pLibInfo->GetLibName(), DialogMask::ButtonsOk ); 925 aErrors.emplace_back(*pErrInf, BasicErrorReason::BASICLOADERROR); 926 } 927 else 928 { 929 // Perhaps there are additional information in the stream... 930 xBasicStream->SetCryptMaskKey(szCryptingKey); 931 xBasicStream->RefreshBuffer(); 932 sal_uInt32 nPasswordMarker = 0; 933 xBasicStream->ReadUInt32( nPasswordMarker ); 934 if ( ( nPasswordMarker == PASSWORD_MARKER ) && !xBasicStream->eof() ) 935 { 936 OUString aPassword = xBasicStream->ReadUniOrByteString( 937 xBasicStream->GetStreamCharSet()); 938 pLibInfo->SetPassword( aPassword ); 939 } 940 xBasicStream->SetCryptMaskKey(OString()); 941 CheckModules( pLibInfo->GetLib().get(), pLibInfo->IsReference() ); 942 } 943 return bLoaded; 944 } 945 } 946 } 947 catch (const css::ucb::ContentCreationException&) 948 { 949 } 950 return false; 951 } 952 953 bool BasicManager::ImplEncryptStream( SvStream& rStrm ) 954 { 955 sal_uInt64 const nPos = rStrm.Tell(); 956 sal_uInt32 nCreator; 957 rStrm.ReadUInt32( nCreator ); 958 rStrm.Seek( nPos ); 959 bool bProtected = false; 960 if ( nCreator != SBXCR_SBX ) 961 { 962 // Should only be the case for encrypted Streams 963 bProtected = true; 964 rStrm.SetCryptMaskKey(szCryptingKey); 965 rStrm.RefreshBuffer(); 966 } 967 return bProtected; 968 } 969 970 // This code is necessary to load the BASIC of Beta 1 971 // TODO: Which Beta 1? 972 bool BasicManager::ImplLoadBasic( SvStream& rStrm, StarBASICRef& rOldBasic ) const 973 { 974 bool bProtected = ImplEncryptStream( rStrm ); 975 SbxBaseRef xNew = SbxBase::Load( rStrm ); 976 bool bLoaded = false; 977 if( xNew.is() ) 978 { 979 if( auto pNew = dynamic_cast<StarBASIC*>( xNew.get() ) ) 980 { 981 // Use the Parent of the old BASICs 982 if( rOldBasic.is() ) 983 { 984 pNew->SetParent( rOldBasic->GetParent() ); 985 if( pNew->GetParent() ) 986 { 987 pNew->GetParent()->Insert( pNew ); 988 } 989 pNew->SetFlag( SbxFlagBits::ExtSearch ); 990 } 991 rOldBasic = pNew; 992 993 // Fill new library container (5.2 -> 6.0) 994 copyToLibraryContainer( pNew, mpImpl->maContainerInfo ); 995 996 pNew->SetModified( false ); 997 bLoaded = true; 998 } 999 } 1000 if ( bProtected ) 1001 { 1002 rStrm.SetCryptMaskKey(OString()); 1003 } 1004 return bLoaded; 1005 } 1006 1007 void BasicManager::CheckModules( StarBASIC* pLib, bool bReference ) 1008 { 1009 if ( !pLib ) 1010 { 1011 return; 1012 } 1013 bool bModified = pLib->IsModified(); 1014 1015 for ( const auto& pModule: pLib->GetModules() ) 1016 { 1017 DBG_ASSERT(pModule, "Module not received!"); 1018 if ( !pModule->IsCompiled() && !StarBASIC::GetErrorCode() ) 1019 { 1020 pModule->Compile(); 1021 } 1022 } 1023 1024 // #67477, AB 8.12.99 On demand compile in referenced libs should not 1025 // cause modified 1026 if( !bModified && bReference ) 1027 { 1028 OSL_FAIL( "Referenced basic library is not compiled!" ); 1029 pLib->SetModified( false ); 1030 } 1031 } 1032 1033 StarBASIC* BasicManager::AddLib( SotStorage& rStorage, const OUString& rLibName, bool bReference ) 1034 { 1035 OUString aStorName( rStorage.GetName() ); 1036 DBG_ASSERT( !aStorName.isEmpty(), "No Storage Name!" ); 1037 1038 OUString aStorageName = INetURLObject(aStorName, INetProtocol::File).GetMainURL( INetURLObject::DecodeMechanism::NONE ); 1039 DBG_ASSERT(!aStorageName.isEmpty(), "Bad storage name"); 1040 1041 OUString aNewLibName( rLibName ); 1042 while ( HasLib( aNewLibName ) ) 1043 { 1044 aNewLibName += "_"; 1045 } 1046 BasicLibInfo* pLibInfo = CreateLibInfo(); 1047 // Use original name otherwise ImpLoadLibrary fails... 1048 pLibInfo->SetLibName( rLibName ); 1049 // but doesn't work this way if name exists twice 1050 sal_uInt16 nLibId = static_cast<sal_uInt16>(mpImpl->aLibs.size()) - 1; 1051 1052 // Set StorageName before load because it is compared with pCurStorage 1053 pLibInfo->SetStorageName( aStorageName ); 1054 bool bLoaded = ImpLoadLibrary( pLibInfo, &rStorage ); 1055 1056 if ( bLoaded ) 1057 { 1058 if ( aNewLibName != rLibName ) 1059 { 1060 pLibInfo->SetLibName(aNewLibName); 1061 } 1062 if ( bReference ) 1063 { 1064 pLibInfo->GetLib()->SetModified( false ); // Don't save in this case 1065 pLibInfo->SetRelStorageName( OUString() ); 1066 pLibInfo->SetReference(true); 1067 } 1068 else 1069 { 1070 pLibInfo->GetLib()->SetModified( true ); // Must be saved after Add! 1071 pLibInfo->SetStorageName( szImbedded ); // Save in BasicManager-Storage 1072 } 1073 } 1074 else 1075 { 1076 RemoveLib( nLibId, false ); 1077 pLibInfo = nullptr; 1078 } 1079 1080 return pLibInfo ? &*pLibInfo->GetLib() : nullptr; 1081 1082 } 1083 1084 bool BasicManager::IsReference( sal_uInt16 nLib ) 1085 { 1086 DBG_ASSERT( nLib < mpImpl->aLibs.size(), "Lib does not exist!" ); 1087 if ( nLib < mpImpl->aLibs.size() ) 1088 { 1089 return mpImpl->aLibs[nLib]->IsReference(); 1090 } 1091 return false; 1092 } 1093 1094 void BasicManager::RemoveLib( sal_uInt16 nLib ) 1095 { 1096 // Only physical deletion if no reference 1097 RemoveLib( nLib, !IsReference( nLib ) ); 1098 } 1099 1100 bool BasicManager::RemoveLib( sal_uInt16 nLib, bool bDelBasicFromStorage ) 1101 { 1102 DBG_ASSERT( nLib, "Standard-Lib cannot be removed!" ); 1103 1104 DBG_ASSERT( !nLib || nLib < mpImpl->aLibs.size(), "Lib not found!" ); 1105 1106 if( !nLib || nLib < mpImpl->aLibs.size() ) 1107 { 1108 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_REMOVELIB, OUString(), DialogMask::ButtonsOk ); 1109 aErrors.emplace_back(*pErrInf, BasicErrorReason::STDLIB); 1110 return false; 1111 } 1112 1113 auto const itLibInfo = mpImpl->aLibs.begin() + nLib; 1114 1115 // If one of the streams cannot be opened, this is not an error, 1116 // because BASIC was never written before... 1117 if (bDelBasicFromStorage && !(*itLibInfo)->IsReference() && 1118 (!(*itLibInfo)->IsExtern() || SotStorage::IsStorageFile((*itLibInfo)->GetStorageName()))) 1119 { 1120 tools::SvRef<SotStorage> xStorage; 1121 try 1122 { 1123 if (!(*itLibInfo)->IsExtern()) 1124 { 1125 xStorage = new SotStorage(false, GetStorageName()); 1126 } 1127 else 1128 { 1129 xStorage = new SotStorage(false, (*itLibInfo)->GetStorageName()); 1130 } 1131 } 1132 catch (const css::ucb::ContentCreationException& e) 1133 { 1134 SAL_WARN("basic", "BasicManager::RemoveLib: " << e); 1135 } 1136 1137 if (xStorage.is() && xStorage->IsStorage(szBasicStorage)) 1138 { 1139 tools::SvRef<SotStorage> xBasicStorage = xStorage->OpenSotStorage 1140 ( szBasicStorage, StreamMode::STD_READWRITE, false ); 1141 1142 if ( !xBasicStorage.is() || xBasicStorage->GetError() ) 1143 { 1144 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_REMOVELIB, OUString(), DialogMask::ButtonsOk ); 1145 aErrors.emplace_back(*pErrInf, BasicErrorReason::OPENLIBSTORAGE); 1146 } 1147 else if (xBasicStorage->IsStream((*itLibInfo)->GetLibName())) 1148 { 1149 xBasicStorage->Remove((*itLibInfo)->GetLibName()); 1150 xBasicStorage->Commit(); 1151 1152 // If no further stream available, 1153 // delete the SubStorage. 1154 SvStorageInfoList aInfoList; 1155 xBasicStorage->FillInfoList( &aInfoList ); 1156 if ( aInfoList.empty() ) 1157 { 1158 xBasicStorage.clear(); 1159 xStorage->Remove( szBasicStorage ); 1160 xStorage->Commit(); 1161 // If no further Streams or SubStorages available, 1162 // delete the Storage, too. 1163 aInfoList.clear(); 1164 xStorage->FillInfoList( &aInfoList ); 1165 if ( aInfoList.empty() ) 1166 { 1167 //OUString aName_( xStorage->GetName() ); 1168 xStorage.clear(); 1169 //*** TODO: Replace if still necessary 1170 //SfxContentHelper::Kill( aName ); 1171 //*** TODO-End 1172 } 1173 } 1174 } 1175 } 1176 } 1177 if ((*itLibInfo)->GetLib().is()) 1178 { 1179 GetStdLib()->Remove( (*itLibInfo)->GetLib().get() ); 1180 } 1181 mpImpl->aLibs.erase(itLibInfo); 1182 return true; // Remove was successful, del unimportant 1183 } 1184 1185 sal_uInt16 BasicManager::GetLibCount() const 1186 { 1187 return static_cast<sal_uInt16>(mpImpl->aLibs.size()); 1188 } 1189 1190 StarBASIC* BasicManager::GetLib( sal_uInt16 nLib ) const 1191 { 1192 DBG_ASSERT( nLib < mpImpl->aLibs.size(), "Lib does not exist!" ); 1193 if ( nLib < mpImpl->aLibs.size() ) 1194 { 1195 return mpImpl->aLibs[nLib]->GetLib().get(); 1196 } 1197 return nullptr; 1198 } 1199 1200 StarBASIC* BasicManager::GetStdLib() const 1201 { 1202 StarBASIC* pLib = GetLib( 0 ); 1203 return pLib; 1204 } 1205 1206 StarBASIC* BasicManager::GetLib( const OUString& rName ) const 1207 { 1208 for (auto const& rpLib : mpImpl->aLibs) 1209 { 1210 if (rpLib->GetLibName().equalsIgnoreAsciiCase(rName)) // Check if available... 1211 { 1212 return rpLib->GetLib().get(); 1213 } 1214 } 1215 return nullptr; 1216 } 1217 1218 sal_uInt16 BasicManager::GetLibId( const OUString& rName ) const 1219 { 1220 for (size_t i = 0; i < mpImpl->aLibs.size(); i++) 1221 { 1222 if (mpImpl->aLibs[i]->GetLibName().equalsIgnoreAsciiCase( rName )) 1223 { 1224 return static_cast<sal_uInt16>(i); 1225 } 1226 } 1227 return LIB_NOTFOUND; 1228 } 1229 1230 bool BasicManager::HasLib( const OUString& rName ) const 1231 { 1232 for (const auto& rpLib : mpImpl->aLibs) 1233 { 1234 if (rpLib->GetLibName().equalsIgnoreAsciiCase(rName)) // Check if available... 1235 { 1236 return true; 1237 } 1238 } 1239 return false; 1240 } 1241 1242 OUString BasicManager::GetLibName( sal_uInt16 nLib ) 1243 { 1244 DBG_ASSERT( nLib < mpImpl->aLibs.size(), "Lib?!" ); 1245 if ( nLib < mpImpl->aLibs.size() ) 1246 { 1247 return mpImpl->aLibs[nLib]->GetLibName(); 1248 } 1249 return OUString(); 1250 } 1251 1252 bool BasicManager::LoadLib( sal_uInt16 nLib ) 1253 { 1254 bool bDone = false; 1255 DBG_ASSERT( nLib < mpImpl->aLibs.size() , "Lib?!" ); 1256 if ( nLib < mpImpl->aLibs.size() ) 1257 { 1258 BasicLibInfo& rLibInfo = *mpImpl->aLibs[nLib]; 1259 uno::Reference< script::XLibraryContainer > xLibContainer = rLibInfo.GetLibraryContainer(); 1260 if( xLibContainer.is() ) 1261 { 1262 OUString aLibName = rLibInfo.GetLibName(); 1263 xLibContainer->loadLibrary( aLibName ); 1264 bDone = xLibContainer->isLibraryLoaded( aLibName ); 1265 } 1266 else 1267 { 1268 bDone = ImpLoadLibrary( &rLibInfo, nullptr ); 1269 StarBASIC* pLib = GetLib( nLib ); 1270 if ( pLib ) 1271 { 1272 GetStdLib()->Insert( pLib ); 1273 pLib->SetFlag( SbxFlagBits::ExtSearch ); 1274 } 1275 } 1276 } 1277 else 1278 { 1279 StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD, OUString(), DialogMask::ButtonsOk ); 1280 aErrors.emplace_back(*pErrInf, BasicErrorReason::LIBNOTFOUND); 1281 } 1282 return bDone; 1283 } 1284 1285 StarBASIC* BasicManager::CreateLib( const OUString& rLibName ) 1286 { 1287 if ( GetLib( rLibName ) ) 1288 { 1289 return nullptr; 1290 } 1291 BasicLibInfo* pLibInfo = CreateLibInfo(); 1292 StarBASIC* pNew = new StarBASIC( GetStdLib(), mbDocMgr ); 1293 GetStdLib()->Insert( pNew ); 1294 pNew->SetFlag( SbxFlagBits::ExtSearch | SbxFlagBits::DontStore ); 1295 pLibInfo->SetLib( pNew ); 1296 pLibInfo->SetLibName( rLibName ); 1297 pLibInfo->GetLib()->SetName( rLibName ); 1298 return pLibInfo->GetLib().get(); 1299 } 1300 1301 // For XML import/export: 1302 StarBASIC* BasicManager::CreateLib( const OUString& rLibName, const OUString& Password, 1303 const OUString& LinkTargetURL ) 1304 { 1305 // Ask if lib exists because standard lib is always there 1306 StarBASIC* pLib = GetLib( rLibName ); 1307 if( !pLib ) 1308 { 1309 if( !LinkTargetURL.isEmpty()) 1310 { 1311 try 1312 { 1313 tools::SvRef<SotStorage> xStorage = new SotStorage(false, LinkTargetURL, StreamMode::READ | StreamMode::SHARE_DENYWRITE); 1314 if (!xStorage->GetError()) 1315 { 1316 pLib = AddLib(*xStorage, rLibName, true); 1317 } 1318 } 1319 catch (const css::ucb::ContentCreationException& e) 1320 { 1321 SAL_WARN("basic", "BasicManager::RemoveLib: " << e); 1322 } 1323 DBG_ASSERT( pLib, "XML Import: Linked basic library could not be loaded"); 1324 } 1325 else 1326 { 1327 pLib = CreateLib( rLibName ); 1328 if( Password.isEmpty()) 1329 { 1330 BasicLibInfo* pLibInfo = FindLibInfo( pLib ); 1331 pLibInfo ->SetPassword( Password ); 1332 } 1333 } 1334 //ExternalSourceURL ? 1335 } 1336 return pLib; 1337 } 1338 1339 StarBASIC* BasicManager::CreateLibForLibContainer( const OUString& rLibName, 1340 const uno::Reference< script::XLibraryContainer >& xScriptCont ) 1341 { 1342 if ( GetLib( rLibName ) ) 1343 { 1344 return nullptr; 1345 } 1346 BasicLibInfo* pLibInfo = CreateLibInfo(); 1347 StarBASIC* pNew = new StarBASIC( GetStdLib(), mbDocMgr ); 1348 GetStdLib()->Insert( pNew ); 1349 pNew->SetFlag( SbxFlagBits::ExtSearch | SbxFlagBits::DontStore ); 1350 pLibInfo->SetLib( pNew ); 1351 pLibInfo->SetLibName( rLibName ); 1352 pLibInfo->GetLib()->SetName( rLibName ); 1353 pLibInfo->SetLibraryContainer( xScriptCont ); 1354 return pNew; 1355 } 1356 1357 1358 BasicLibInfo* BasicManager::FindLibInfo( StarBASIC const * pBasic ) 1359 { 1360 for (auto const& rpLib : mpImpl->aLibs) 1361 { 1362 if (rpLib->GetLib().get() == pBasic) 1363 { 1364 return rpLib.get(); 1365 } 1366 } 1367 return nullptr; 1368 } 1369 1370 1371 bool BasicManager::IsBasicModified() const 1372 { 1373 for (auto const& rpLib : mpImpl->aLibs) 1374 { 1375 if (rpLib->GetLib().is() && rpLib->GetLib()->IsModified()) 1376 { 1377 return true; 1378 } 1379 } 1380 return false; 1381 } 1382 1383 1384 bool BasicManager::GetGlobalUNOConstant( const OUString& rName, uno::Any& aOut ) 1385 { 1386 bool bRes = false; 1387 StarBASIC* pStandardLib = GetStdLib(); 1388 OSL_PRECOND( pStandardLib, "BasicManager::GetGlobalUNOConstant: no lib to read from!" ); 1389 if ( pStandardLib ) 1390 bRes = pStandardLib->GetUNOConstant( rName, aOut ); 1391 return bRes; 1392 } 1393 1394 uno::Any BasicManager::SetGlobalUNOConstant( const OUString& rName, const uno::Any& _rValue ) 1395 { 1396 uno::Any aOldValue; 1397 1398 StarBASIC* pStandardLib = GetStdLib(); 1399 OSL_PRECOND( pStandardLib, "BasicManager::SetGlobalUNOConstant: no lib to insert into!" ); 1400 if ( !pStandardLib ) 1401 return aOldValue; 1402 1403 // obtain the old value 1404 SbxVariable* pVariable = pStandardLib->Find( rName, SbxClassType::Object ); 1405 if ( pVariable ) 1406 aOldValue = sbxToUnoValue( pVariable ); 1407 1408 SbxObjectRef xUnoObj = GetSbUnoObject( rName, _rValue ); 1409 xUnoObj->SetFlag( SbxFlagBits::DontStore ); 1410 pStandardLib->Insert( xUnoObj.get() ); 1411 1412 return aOldValue; 1413 } 1414 1415 bool BasicManager::LegacyPsswdBinaryLimitExceeded( std::vector< OUString >& _out_rModuleNames ) 1416 { 1417 try 1418 { 1419 uno::Reference< container::XNameAccess > xScripts( GetScriptLibraryContainer(), uno::UNO_QUERY_THROW ); 1420 uno::Reference< script::XLibraryContainerPassword > xPassword( GetScriptLibraryContainer(), uno::UNO_QUERY_THROW ); 1421 1422 uno::Sequence< OUString > aNames( xScripts->getElementNames() ); 1423 for ( auto const & scriptElementName : aNames ) 1424 { 1425 if( !xPassword->isLibraryPasswordProtected( scriptElementName ) ) 1426 continue; 1427 1428 StarBASIC* pBasicLib = GetLib( scriptElementName ); 1429 if ( !pBasicLib ) 1430 continue; 1431 1432 uno::Reference< container::XNameAccess > xScriptLibrary( xScripts->getByName( scriptElementName ), uno::UNO_QUERY_THROW ); 1433 uno::Sequence< OUString > aElementNames( xScriptLibrary->getElementNames() ); 1434 sal_Int32 nLen = aElementNames.getLength(); 1435 1436 std::vector< OUString > aBigModules( nLen ); 1437 sal_Int32 nBigModules = 0; 1438 1439 for ( auto const & libraryElementName : aElementNames ) 1440 { 1441 SbModule* pMod = pBasicLib->FindModule( libraryElementName ); 1442 if ( pMod && pMod->ExceedsLegacyModuleSize() ) 1443 aBigModules[ nBigModules++ ] = libraryElementName; 1444 } 1445 1446 if ( nBigModules ) 1447 { 1448 _out_rModuleNames.swap(aBigModules); 1449 return true; 1450 } 1451 } 1452 } 1453 catch( const uno::Exception& ) 1454 { 1455 DBG_UNHANDLED_EXCEPTION("basic"); 1456 } 1457 return false; 1458 } 1459 1460 1461 namespace 1462 { 1463 SbMethod* lcl_queryMacro( BasicManager* i_manager, OUString const& i_fullyQualifiedName ) 1464 { 1465 sal_Int32 nLast = 0; 1466 const OUString sLibName {i_fullyQualifiedName.getToken( 0, '.', nLast )}; 1467 const OUString sModule {i_fullyQualifiedName.getToken( 0, '.', nLast )}; 1468 OUString sMacro; 1469 if(nLast >= 0) 1470 { 1471 sMacro = i_fullyQualifiedName.copy(nLast); 1472 } 1473 else 1474 { 1475 sMacro = i_fullyQualifiedName; 1476 } 1477 1478 utl::TransliterationWrapper& rTransliteration = SbGlobal::GetTransliteration(); 1479 sal_uInt16 nLibCount = i_manager->GetLibCount(); 1480 for ( sal_uInt16 nLib = 0; nLib < nLibCount; ++nLib ) 1481 { 1482 if ( rTransliteration.isEqual( i_manager->GetLibName( nLib ), sLibName ) ) 1483 { 1484 StarBASIC* pLib = i_manager->GetLib( nLib ); 1485 if( !pLib ) 1486 { 1487 bool const bLoaded = i_manager->LoadLib( nLib ); 1488 if (bLoaded) 1489 { 1490 pLib = i_manager->GetLib( nLib ); 1491 } 1492 } 1493 1494 if( pLib ) 1495 { 1496 for ( const auto& pMod: pLib->GetModules() ) 1497 { 1498 if ( rTransliteration.isEqual( pMod->GetName(), sModule ) ) 1499 { 1500 SbMethod* pMethod = static_cast<SbMethod*>(pMod->Find( sMacro, SbxClassType::Method )); 1501 if( pMethod ) 1502 { 1503 return pMethod; 1504 } 1505 } 1506 } 1507 } 1508 } 1509 } 1510 return nullptr; 1511 } 1512 } 1513 1514 bool BasicManager::HasMacro( OUString const& i_fullyQualifiedName ) const 1515 { 1516 return ( lcl_queryMacro( const_cast< BasicManager* >( this ), i_fullyQualifiedName ) != nullptr ); 1517 } 1518 1519 ErrCode BasicManager::ExecuteMacro( OUString const& i_fullyQualifiedName, SbxArray* i_arguments, SbxValue* i_retValue ) 1520 { 1521 SbMethod* pMethod = lcl_queryMacro( this, i_fullyQualifiedName ); 1522 ErrCode nError = ERRCODE_NONE; 1523 if ( pMethod ) 1524 { 1525 if ( i_arguments ) 1526 pMethod->SetParameters( i_arguments ); 1527 nError = pMethod->Call( i_retValue ); 1528 } 1529 else 1530 nError = ERRCODE_BASIC_PROC_UNDEFINED; 1531 return nError; 1532 } 1533 1534 ErrCode BasicManager::ExecuteMacro( OUString const& i_fullyQualifiedName, OUString const& i_commaSeparatedArgs, SbxValue* i_retValue ) 1535 { 1536 SbMethod* pMethod = lcl_queryMacro( this, i_fullyQualifiedName ); 1537 if ( !pMethod ) 1538 { 1539 return ERRCODE_BASIC_PROC_UNDEFINED; 1540 } 1541 // arguments must be quoted 1542 OUString sQuotedArgs; 1543 OUStringBuffer sArgs( i_commaSeparatedArgs ); 1544 if ( sArgs.getLength()<2 || sArgs[1] == '\"') 1545 { 1546 // no args or already quoted args 1547 sQuotedArgs = sArgs.makeStringAndClear(); 1548 } 1549 else 1550 { 1551 // quote parameters 1552 sArgs.remove( 0, 1 ); 1553 sArgs.remove( sArgs.getLength() - 1, 1 ); 1554 1555 OUStringBuffer aBuff; 1556 OUString sArgs2 = sArgs.makeStringAndClear(); 1557 1558 aBuff.append("("); 1559 if (!sArgs2.isEmpty()) 1560 { 1561 1562 sal_Int32 nPos {0}; 1563 for (;;) 1564 { 1565 aBuff.append( "\"" ); 1566 aBuff.append( sArgs2.getToken(0, ',', nPos) ); 1567 aBuff.append( "\"" ); 1568 if (nPos<0) 1569 break; 1570 aBuff.append( "," ); 1571 } 1572 } 1573 aBuff.append( ")" ); 1574 1575 sQuotedArgs = aBuff.makeStringAndClear(); 1576 } 1577 1578 // add quoted arguments and do the call 1579 OUString sCall = "[" 1580 + pMethod->GetName() 1581 + sQuotedArgs 1582 + "]"; 1583 1584 SbxVariable* pRet = pMethod->GetParent()->Execute( sCall ); 1585 if ( pRet && ( pRet != pMethod ) ) 1586 { 1587 *i_retValue = *pRet; 1588 } 1589 return SbxBase::GetError(); 1590 } 1591 1592 1593 class ModuleInfo_Impl : public ModuleInfoHelper 1594 { 1595 OUString maName; 1596 OUString maLanguage; 1597 OUString maSource; 1598 1599 public: 1600 ModuleInfo_Impl( const OUString& aName, const OUString& aLanguage, const OUString& aSource ) 1601 : maName( aName ), maLanguage( aLanguage), maSource( aSource ) {} 1602 1603 // Methods XStarBasicModuleInfo 1604 virtual OUString SAL_CALL getName() override 1605 { return maName; } 1606 virtual OUString SAL_CALL getLanguage() override 1607 { return maLanguage; } 1608 virtual OUString SAL_CALL getSource() override 1609 { return maSource; } 1610 }; 1611 1612 1613 class DialogInfo_Impl : public WeakImplHelper< script::XStarBasicDialogInfo > 1614 { 1615 OUString maName; 1616 uno::Sequence< sal_Int8 > mData; 1617 1618 public: 1619 DialogInfo_Impl( const OUString& aName, const uno::Sequence< sal_Int8 >& Data ) 1620 : maName( aName ), mData( Data ) {} 1621 1622 // Methods XStarBasicDialogInfo 1623 virtual OUString SAL_CALL getName() override 1624 { return maName; } 1625 virtual uno::Sequence< sal_Int8 > SAL_CALL getData() override 1626 { return mData; } 1627 }; 1628 1629 1630 class LibraryInfo_Impl : public WeakImplHelper< script::XStarBasicLibraryInfo > 1631 { 1632 OUString maName; 1633 uno::Reference< container::XNameContainer > mxModuleContainer; 1634 uno::Reference< container::XNameContainer > mxDialogContainer; 1635 OUString maPassword; 1636 OUString maExternaleSourceURL; 1637 OUString maLinkTargetURL; 1638 1639 public: 1640 LibraryInfo_Impl 1641 ( 1642 const OUString& aName, 1643 uno::Reference< container::XNameContainer > const & xModuleContainer, 1644 uno::Reference< container::XNameContainer > const & xDialogContainer, 1645 const OUString& aPassword, 1646 const OUString& aExternaleSourceURL, 1647 const OUString& aLinkTargetURL 1648 ) 1649 : maName( aName ) 1650 , mxModuleContainer( xModuleContainer ) 1651 , mxDialogContainer( xDialogContainer ) 1652 , maPassword( aPassword ) 1653 , maExternaleSourceURL( aExternaleSourceURL ) 1654 , maLinkTargetURL( aLinkTargetURL ) 1655 {} 1656 1657 // Methods XStarBasicLibraryInfo 1658 virtual OUString SAL_CALL getName() override 1659 { return maName; } 1660 virtual uno::Reference< container::XNameContainer > SAL_CALL getModuleContainer() override 1661 { return mxModuleContainer; } 1662 virtual uno::Reference< container::XNameContainer > SAL_CALL getDialogContainer() override 1663 { return mxDialogContainer; } 1664 virtual OUString SAL_CALL getPassword() override 1665 { return maPassword; } 1666 virtual OUString SAL_CALL getExternalSourceURL() override 1667 { return maExternaleSourceURL; } 1668 virtual OUString SAL_CALL getLinkTargetURL() override 1669 { return maLinkTargetURL; } 1670 }; 1671 1672 1673 class ModuleContainer_Impl : public NameContainerHelper 1674 { 1675 StarBASIC* mpLib; 1676 1677 public: 1678 explicit ModuleContainer_Impl( StarBASIC* pLib ) 1679 :mpLib( pLib ) {} 1680 1681 // Methods XElementAccess 1682 virtual uno::Type SAL_CALL getElementType() override; 1683 virtual sal_Bool SAL_CALL hasElements() override; 1684 1685 // Methods XNameAccess 1686 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override; 1687 virtual uno::Sequence< OUString > SAL_CALL getElementNames() override; 1688 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; 1689 1690 // Methods XNameReplace 1691 virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override; 1692 1693 // Methods XNameContainer 1694 virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override; 1695 virtual void SAL_CALL removeByName( const OUString& Name ) override; 1696 }; 1697 1698 // Methods XElementAccess 1699 uno::Type ModuleContainer_Impl::getElementType() 1700 { 1701 uno::Type aModuleType = cppu::UnoType<script::XStarBasicModuleInfo>::get(); 1702 return aModuleType; 1703 } 1704 1705 sal_Bool ModuleContainer_Impl::hasElements() 1706 { 1707 return mpLib && !mpLib->GetModules().empty(); 1708 } 1709 1710 // Methods XNameAccess 1711 uno::Any ModuleContainer_Impl::getByName( const OUString& aName ) 1712 { 1713 SbModule* pMod = mpLib ? mpLib->FindModule( aName ) : nullptr; 1714 if( !pMod ) 1715 throw container::NoSuchElementException(); 1716 uno::Reference< script::XStarBasicModuleInfo > xMod = new ModuleInfo_Impl( aName, "StarBasic", pMod->GetSource32() ); 1717 uno::Any aRetAny; 1718 aRetAny <<= xMod; 1719 return aRetAny; 1720 } 1721 1722 uno::Sequence< OUString > ModuleContainer_Impl::getElementNames() 1723 { 1724 sal_uInt16 nMods = mpLib ? mpLib->GetModules().size() : 0; 1725 uno::Sequence< OUString > aRetSeq( nMods ); 1726 OUString* pRetSeq = aRetSeq.getArray(); 1727 for( sal_uInt16 i = 0 ; i < nMods ; i++ ) 1728 { 1729 pRetSeq[i] = mpLib->GetModules()[i]->GetName(); 1730 } 1731 return aRetSeq; 1732 } 1733 1734 sal_Bool ModuleContainer_Impl::hasByName( const OUString& aName ) 1735 { 1736 SbModule* pMod = mpLib ? mpLib->FindModule( aName ) : nullptr; 1737 bool bRet = (pMod != nullptr); 1738 return bRet; 1739 } 1740 1741 1742 // Methods XNameReplace 1743 void ModuleContainer_Impl::replaceByName( const OUString& aName, const uno::Any& aElement ) 1744 { 1745 removeByName( aName ); 1746 insertByName( aName, aElement ); 1747 } 1748 1749 1750 // Methods XNameContainer 1751 void ModuleContainer_Impl::insertByName( const OUString& aName, const uno::Any& aElement ) 1752 { 1753 uno::Type aModuleType = cppu::UnoType<script::XStarBasicModuleInfo>::get(); 1754 const uno::Type& aAnyType = aElement.getValueType(); 1755 if( aModuleType != aAnyType ) 1756 { 1757 throw lang::IllegalArgumentException(); 1758 } 1759 uno::Reference< script::XStarBasicModuleInfo > xMod; 1760 aElement >>= xMod; 1761 mpLib->MakeModule( aName, xMod->getSource() ); 1762 } 1763 1764 void ModuleContainer_Impl::removeByName( const OUString& Name ) 1765 { 1766 SbModule* pMod = mpLib ? mpLib->FindModule( Name ) : nullptr; 1767 if( !pMod ) 1768 { 1769 throw container::NoSuchElementException(); 1770 } 1771 mpLib->Remove( pMod ); 1772 } 1773 1774 1775 static uno::Sequence< sal_Int8 > implGetDialogData( SbxObject* pDialog ) 1776 { 1777 SvMemoryStream aMemStream; 1778 pDialog->Store( aMemStream ); 1779 sal_Int32 nLen = aMemStream.Tell(); 1780 if (nLen < 0) { abort(); } 1781 uno::Sequence< sal_Int8 > aData( nLen ); 1782 sal_Int8* pDestData = aData.getArray(); 1783 const sal_Int8* pSrcData = static_cast<const sal_Int8*>(aMemStream.GetData()); 1784 memcpy( pDestData, pSrcData, nLen ); 1785 return aData; 1786 } 1787 1788 static SbxObject* implCreateDialog( const uno::Sequence< sal_Int8 >& aData ) 1789 { 1790 sal_Int8* pData = const_cast< uno::Sequence< sal_Int8 >& >(aData).getArray(); 1791 SvMemoryStream aMemStream( pData, aData.getLength(), StreamMode::READ ); 1792 SbxBase* pBase = SbxBase::Load( aMemStream ); 1793 return dynamic_cast<SbxObject*>(pBase); 1794 } 1795 1796 // HACK! Because this value is defined in basctl/inc/vcsbxdef.hxx 1797 // which we can't include here, we have to use the value directly 1798 #define SBXID_DIALOG 101 1799 1800 1801 class DialogContainer_Impl : public NameContainerHelper 1802 { 1803 StarBASIC* mpLib; 1804 1805 public: 1806 explicit DialogContainer_Impl( StarBASIC* pLib ) 1807 :mpLib( pLib ) {} 1808 1809 // Methods XElementAccess 1810 virtual uno::Type SAL_CALL getElementType() override; 1811 virtual sal_Bool SAL_CALL hasElements() override; 1812 1813 // Methods XNameAccess 1814 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override; 1815 virtual uno::Sequence< OUString > SAL_CALL getElementNames() override; 1816 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; 1817 1818 // Methods XNameReplace 1819 virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override; 1820 1821 // Methods XNameContainer 1822 virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override; 1823 virtual void SAL_CALL removeByName( const OUString& Name ) override; 1824 }; 1825 1826 // Methods XElementAccess 1827 uno::Type DialogContainer_Impl::getElementType() 1828 { 1829 uno::Type aModuleType = cppu::UnoType<script::XStarBasicDialogInfo>::get(); 1830 return aModuleType; 1831 } 1832 1833 sal_Bool DialogContainer_Impl::hasElements() 1834 { 1835 bool bRet = false; 1836 1837 sal_Int16 nCount = mpLib->GetObjects()->Count(); 1838 for( sal_Int16 nObj = 0; nObj < nCount ; nObj++ ) 1839 { 1840 SbxVariable* pVar = mpLib->GetObjects()->Get( nObj ); 1841 SbxObject* pObj = dynamic_cast<SbxObject*>(pVar); 1842 if ( pObj && (pObj->GetSbxId() == SBXID_DIALOG ) ) 1843 { 1844 bRet = true; 1845 break; 1846 } 1847 } 1848 return bRet; 1849 } 1850 1851 // Methods XNameAccess 1852 uno::Any DialogContainer_Impl::getByName( const OUString& aName ) 1853 { 1854 SbxVariable* pVar = mpLib->GetObjects()->Find( aName, SbxClassType::DontCare ); 1855 SbxObject* pObj = dynamic_cast<SbxObject*>(pVar); 1856 if( !( pObj && pObj->GetSbxId() == SBXID_DIALOG ) ) 1857 { 1858 throw container::NoSuchElementException(); 1859 } 1860 1861 uno::Reference< script::XStarBasicDialogInfo > xDialog = 1862 new DialogInfo_Impl(aName, implGetDialogData(pObj)); 1863 1864 uno::Any aRetAny; 1865 aRetAny <<= xDialog; 1866 return aRetAny; 1867 } 1868 1869 uno::Sequence< OUString > DialogContainer_Impl::getElementNames() 1870 { 1871 sal_Int16 nCount = mpLib->GetObjects()->Count(); 1872 uno::Sequence< OUString > aRetSeq( nCount ); 1873 OUString* pRetSeq = aRetSeq.getArray(); 1874 sal_Int32 nDialogCounter = 0; 1875 1876 for( sal_Int16 nObj = 0; nObj < nCount ; nObj++ ) 1877 { 1878 SbxVariable* pVar = mpLib->GetObjects()->Get( nObj ); 1879 SbxObject* pObj = dynamic_cast<SbxObject*> (pVar); 1880 if ( pObj && ( pObj->GetSbxId() == SBXID_DIALOG ) ) 1881 { 1882 pRetSeq[ nDialogCounter ] = pVar->GetName(); 1883 nDialogCounter++; 1884 } 1885 } 1886 aRetSeq.realloc( nDialogCounter ); 1887 return aRetSeq; 1888 } 1889 1890 sal_Bool DialogContainer_Impl::hasByName( const OUString& aName ) 1891 { 1892 bool bRet = false; 1893 SbxVariable* pVar = mpLib->GetObjects()->Find( aName, SbxClassType::DontCare ); 1894 SbxObject* pObj = dynamic_cast<SbxObject*>(pVar); 1895 if( pObj && ( pObj->GetSbxId() == SBXID_DIALOG ) ) 1896 { 1897 bRet = true; 1898 } 1899 return bRet; 1900 } 1901 1902 1903 // Methods XNameReplace 1904 void DialogContainer_Impl::replaceByName( const OUString& aName, const uno::Any& aElement ) 1905 { 1906 removeByName( aName ); 1907 insertByName( aName, aElement ); 1908 } 1909 1910 1911 // Methods XNameContainer 1912 void DialogContainer_Impl::insertByName( const OUString&, const uno::Any& aElement ) 1913 { 1914 uno::Type aModuleType = cppu::UnoType<script::XStarBasicDialogInfo>::get(); 1915 const uno::Type& aAnyType = aElement.getValueType(); 1916 if( aModuleType != aAnyType ) 1917 { 1918 throw lang::IllegalArgumentException(); 1919 } 1920 uno::Reference< script::XStarBasicDialogInfo > xMod; 1921 aElement >>= xMod; 1922 SbxObjectRef xDialog = implCreateDialog( xMod->getData() ); 1923 mpLib->Insert( xDialog.get() ); 1924 } 1925 1926 void DialogContainer_Impl::removeByName( const OUString& Name ) 1927 { 1928 SbxVariable* pVar = mpLib->GetObjects()->Find( Name, SbxClassType::DontCare ); 1929 SbxObject* pObj = dynamic_cast<SbxObject*>(pVar); 1930 if( !( pObj && ( pObj->GetSbxId() == SBXID_DIALOG ) ) ) 1931 { 1932 throw container::NoSuchElementException(); 1933 } 1934 mpLib->Remove( pVar ); 1935 } 1936 1937 1938 class LibraryContainer_Impl : public NameContainerHelper 1939 { 1940 BasicManager* mpMgr; 1941 1942 public: 1943 explicit LibraryContainer_Impl( BasicManager* pMgr ) 1944 :mpMgr( pMgr ) {} 1945 1946 // Methods XElementAccess 1947 virtual uno::Type SAL_CALL getElementType() override; 1948 virtual sal_Bool SAL_CALL hasElements() override; 1949 1950 // Methods XNameAccess 1951 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override; 1952 virtual uno::Sequence< OUString > SAL_CALL getElementNames() override; 1953 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; 1954 1955 // Methods XNameReplace 1956 virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override; 1957 1958 // Methods XNameContainer 1959 virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override; 1960 virtual void SAL_CALL removeByName( const OUString& Name ) override; 1961 }; 1962 1963 1964 // Methods XElementAccess 1965 uno::Type LibraryContainer_Impl::getElementType() 1966 { 1967 uno::Type aType = cppu::UnoType<script::XStarBasicLibraryInfo>::get(); 1968 return aType; 1969 } 1970 1971 sal_Bool LibraryContainer_Impl::hasElements() 1972 { 1973 sal_Int32 nLibs = mpMgr->GetLibCount(); 1974 bool bRet = (nLibs > 0); 1975 return bRet; 1976 } 1977 1978 // Methods XNameAccess 1979 uno::Any LibraryContainer_Impl::getByName( const OUString& aName ) 1980 { 1981 uno::Any aRetAny; 1982 if( !mpMgr->HasLib( aName ) ) 1983 throw container::NoSuchElementException(); 1984 StarBASIC* pLib = mpMgr->GetLib( aName ); 1985 1986 uno::Reference< container::XNameContainer > xModuleContainer = 1987 new ModuleContainer_Impl( pLib ); 1988 1989 uno::Reference< container::XNameContainer > xDialogContainer = 1990 new DialogContainer_Impl( pLib ); 1991 1992 BasicLibInfo* pLibInfo = mpMgr->FindLibInfo( pLib ); 1993 1994 OUString aPassword = pLibInfo->GetPassword(); 1995 1996 // TODO Only provide extern info! 1997 OUString aExternaleSourceURL; 1998 OUString aLinkTargetURL; 1999 if( pLibInfo->IsReference() ) 2000 { 2001 aLinkTargetURL = pLibInfo->GetStorageName(); 2002 } 2003 else if( pLibInfo->IsExtern() ) 2004 { 2005 aExternaleSourceURL = pLibInfo->GetStorageName(); 2006 } 2007 uno::Reference< script::XStarBasicLibraryInfo > xLibInfo = new LibraryInfo_Impl 2008 ( 2009 aName, 2010 xModuleContainer, 2011 xDialogContainer, 2012 aPassword, 2013 aExternaleSourceURL, 2014 aLinkTargetURL 2015 ); 2016 2017 aRetAny <<= xLibInfo; 2018 return aRetAny; 2019 } 2020 2021 uno::Sequence< OUString > LibraryContainer_Impl::getElementNames() 2022 { 2023 sal_uInt16 nLibs = mpMgr->GetLibCount(); 2024 uno::Sequence< OUString > aRetSeq( nLibs ); 2025 OUString* pRetSeq = aRetSeq.getArray(); 2026 for( sal_uInt16 i = 0 ; i < nLibs ; i++ ) 2027 { 2028 pRetSeq[i] = mpMgr->GetLibName( i ); 2029 } 2030 return aRetSeq; 2031 } 2032 2033 sal_Bool LibraryContainer_Impl::hasByName( const OUString& aName ) 2034 { 2035 bool bRet = mpMgr->HasLib( aName ); 2036 return bRet; 2037 } 2038 2039 // Methods XNameReplace 2040 void LibraryContainer_Impl::replaceByName( const OUString& aName, const uno::Any& aElement ) 2041 { 2042 removeByName( aName ); 2043 insertByName( aName, aElement ); 2044 } 2045 2046 // Methods XNameContainer 2047 void LibraryContainer_Impl::insertByName( const OUString&, const uno::Any& ) 2048 { 2049 // TODO: Insert a complete Library?! 2050 } 2051 2052 void LibraryContainer_Impl::removeByName( const OUString& Name ) 2053 { 2054 StarBASIC* pLib = mpMgr->GetLib( Name ); 2055 if( !pLib ) 2056 { 2057 throw container::NoSuchElementException(); 2058 } 2059 sal_uInt16 nLibId = mpMgr->GetLibId( Name ); 2060 mpMgr->RemoveLib( nLibId ); 2061 } 2062 2063 2064 typedef WeakImplHelper< script::XStarBasicAccess > StarBasicAccessHelper; 2065 2066 2067 class StarBasicAccess_Impl : public StarBasicAccessHelper 2068 { 2069 BasicManager* mpMgr; 2070 uno::Reference< container::XNameContainer > mxLibContainer; 2071 2072 public: 2073 explicit StarBasicAccess_Impl( BasicManager* pMgr ) 2074 :mpMgr( pMgr ) {} 2075 2076 public: 2077 // Methods 2078 virtual uno::Reference< container::XNameContainer > SAL_CALL getLibraryContainer() override; 2079 virtual void SAL_CALL createLibrary( const OUString& LibName, const OUString& Password, 2080 const OUString& ExternalSourceURL, const OUString& LinkTargetURL ) override; 2081 virtual void SAL_CALL addModule( const OUString& LibraryName, const OUString& ModuleName, 2082 const OUString& Language, const OUString& Source ) override; 2083 virtual void SAL_CALL addDialog( const OUString& LibraryName, const OUString& DialogName, 2084 const uno::Sequence< sal_Int8 >& Data ) override; 2085 }; 2086 2087 uno::Reference< container::XNameContainer > SAL_CALL StarBasicAccess_Impl::getLibraryContainer() 2088 { 2089 if( !mxLibContainer.is() ) 2090 mxLibContainer = new LibraryContainer_Impl( mpMgr ); 2091 return mxLibContainer; 2092 } 2093 2094 void SAL_CALL StarBasicAccess_Impl::createLibrary 2095 ( 2096 const OUString& LibName, 2097 const OUString& Password, 2098 const OUString&, 2099 const OUString& LinkTargetURL 2100 ) 2101 { 2102 StarBASIC* pLib = mpMgr->CreateLib( LibName, Password, LinkTargetURL ); 2103 DBG_ASSERT( pLib, "XML Import: Basic library could not be created"); 2104 } 2105 2106 void SAL_CALL StarBasicAccess_Impl::addModule 2107 ( 2108 const OUString& LibraryName, 2109 const OUString& ModuleName, 2110 const OUString&, 2111 const OUString& Source 2112 ) 2113 { 2114 StarBASIC* pLib = mpMgr->GetLib( LibraryName ); 2115 DBG_ASSERT( pLib, "XML Import: Lib for module unknown"); 2116 if( pLib ) 2117 { 2118 pLib->MakeModule( ModuleName, Source ); 2119 } 2120 } 2121 2122 void SAL_CALL StarBasicAccess_Impl::addDialog 2123 ( 2124 const OUString&, 2125 const OUString&, 2126 const uno::Sequence< sal_Int8 >& 2127 ) 2128 {} 2129 2130 // Basic XML Import/Export 2131 uno::Reference< script::XStarBasicAccess > getStarBasicAccess( BasicManager* pMgr ) 2132 { 2133 uno::Reference< script::XStarBasicAccess > xRet = 2134 new StarBasicAccess_Impl( pMgr ); 2135 return xRet; 2136 } 2137 2138 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 2139
