summaryrefslogtreecommitdiffstats
path: root/basic/source/uno/namecont.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--basic/source/uno/namecont.cxx3498
1 files changed, 3498 insertions, 0 deletions
diff --git a/basic/source/uno/namecont.cxx b/basic/source/uno/namecont.cxx
new file mode 100644
index 000000000..05a1a5b40
--- /dev/null
+++ b/basic/source/uno/namecont.cxx
@@ -0,0 +1,3498 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_extensions.h>
+#include <config_folders.h>
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/ucb/ContentCreationException.hpp>
+#include <com/sun/star/xml/sax/SAXException.hpp>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/errinf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <sot/storage.hxx>
+#include <comphelper/getexpandeduri.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <namecont.hxx>
+#include <basic/basicmanagerrepository.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <unotools/pathoptions.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svtools/ehdl.hxx>
+#include <basic/basmgr.hxx>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/script/LibraryNotLoadedException.hpp>
+#include <com/sun/star/script/vba/VBAScriptEventId.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/util/PathSubstitution.hpp>
+#include <com/sun/star/deployment/ExtensionManager.hpp>
+#include <comphelper/storagehelper.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <memory>
+#include <string_view>
+
+namespace basic
+{
+
+using namespace com::sun::star::document;
+using namespace com::sun::star::container;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::io;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::script;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::xml::sax;
+using namespace com::sun::star::util;
+using namespace com::sun::star::task;
+using namespace com::sun::star::embed;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::deployment;
+using namespace com::sun::star;
+using namespace cppu;
+using namespace osl;
+
+using com::sun::star::uno::Reference;
+
+// #i34411: Flag for error handling during migration
+static bool GbMigrationSuppressErrors = false;
+
+
+// Implementation class NameContainer
+
+// Methods XElementAccess
+Type NameContainer::getElementType()
+{
+ return mType;
+}
+
+sal_Bool NameContainer::hasElements()
+{
+ bool bRet = (mnElementCount > 0);
+ return bRet;
+}
+
+// Methods XNameAccess
+Any NameContainer::getByName( const OUString& aName )
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ if( aIt == mHashMap.end() )
+ {
+ throw NoSuchElementException();
+ }
+ sal_Int32 iHashResult = (*aIt).second;
+ Any aRetAny = mValues[ iHashResult ];
+ return aRetAny;
+}
+
+Sequence< OUString > NameContainer::getElementNames()
+{
+ return comphelper::containerToSequence(mNames);
+}
+
+sal_Bool NameContainer::hasByName( const OUString& aName )
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ bool bRet = ( aIt != mHashMap.end() );
+ return bRet;
+}
+
+
+// Methods XNameReplace
+void NameContainer::replaceByName( const OUString& aName, const Any& aElement )
+{
+ const Type& aAnyType = aElement.getValueType();
+ if( mType != aAnyType )
+ {
+ throw IllegalArgumentException("types do not match", static_cast<cppu::OWeakObject*>(this), 2);
+ }
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ if( aIt == mHashMap.end() )
+ {
+ throw NoSuchElementException();
+ }
+ sal_Int32 iHashResult = (*aIt).second;
+ Any aOldElement = mValues[ iHashResult ];
+ mValues[ iHashResult ] = aElement;
+
+
+ // Fire event
+ if( maContainerListeners.getLength() > 0 )
+ {
+ ContainerEvent aEvent;
+ aEvent.Source = mpxEventSource;
+ aEvent.Accessor <<= aName;
+ aEvent.Element = aElement;
+ aEvent.ReplacedElement = aOldElement;
+ maContainerListeners.notifyEach( &XContainerListener::elementReplaced, aEvent );
+ }
+
+ /* After the container event has been fired (one listener will update the
+ core Basic manager), fire change event. Listeners can rely on that the
+ Basic source code of the core Basic manager is up-to-date. */
+ if( maChangesListeners.getLength() > 0 )
+ {
+ ChangesEvent aEvent;
+ aEvent.Source = mpxEventSource;
+ aEvent.Base <<= aEvent.Source;
+ aEvent.Changes = { { Any(aName), aElement, aOldElement } };
+ maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent );
+ }
+}
+
+void NameContainer::insertCheck(const OUString& aName, const Any& aElement)
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find(aName);
+ if( aIt != mHashMap.end() )
+ {
+ throw ElementExistException();
+ }
+ insertNoCheck(aName, aElement);
+}
+
+void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement)
+{
+ const Type& aAnyType = aElement.getValueType();
+ if( mType != aAnyType )
+ {
+ throw IllegalArgumentException("types do not match", static_cast<cppu::OWeakObject*>(this), 2);
+ }
+
+ sal_Int32 nCount = mNames.size();
+ mNames.push_back( aName );
+ mValues.push_back( aElement );
+
+ mHashMap[ aName ] = nCount;
+ mnElementCount++;
+
+ // Fire event
+ if( maContainerListeners.getLength() > 0 )
+ {
+ ContainerEvent aEvent;
+ aEvent.Source = mpxEventSource;
+ aEvent.Accessor <<= aName;
+ aEvent.Element = aElement;
+ maContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
+ }
+
+ /* After the container event has been fired (one listener will update the
+ core Basic manager), fire change event. Listeners can rely on that the
+ Basic source code of the core Basic manager is up-to-date. */
+ if( maChangesListeners.getLength() > 0 )
+ {
+ ChangesEvent aEvent;
+ aEvent.Source = mpxEventSource;
+ aEvent.Base <<= aEvent.Source;
+ aEvent.Changes = { { Any(aName), aElement, {} } };
+ maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent );
+ }
+}
+
+// Methods XNameContainer
+void NameContainer::insertByName( const OUString& aName, const Any& aElement )
+{
+ insertCheck(aName, aElement);
+}
+
+void NameContainer::removeByName( const OUString& aName )
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ if( aIt == mHashMap.end() )
+ {
+ OUString sMessage = "\"" + aName + "\" not found";
+ throw NoSuchElementException(sMessage);
+ }
+
+ sal_Int32 iHashResult = (*aIt).second;
+ Any aOldElement = mValues[ iHashResult ];
+ mHashMap.erase( aIt );
+ sal_Int32 iLast = mNames.size() - 1;
+ if( iLast != iHashResult )
+ {
+ mNames[ iHashResult ] = mNames[ iLast ];
+ mValues[ iHashResult ] = mValues[ iLast ];
+ mHashMap[ mNames[ iHashResult ] ] = iHashResult;
+ }
+ mNames.resize( iLast );
+ mValues.resize( iLast );
+ mnElementCount--;
+
+ // Fire event
+ if( maContainerListeners.getLength() > 0 )
+ {
+ ContainerEvent aEvent;
+ aEvent.Source = mpxEventSource;
+ aEvent.Accessor <<= aName;
+ aEvent.Element = aOldElement;
+ maContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
+ }
+
+ /* After the container event has been fired (one listener will update the
+ core Basic manager), fire change event. Listeners can rely on that the
+ Basic source code of the core Basic manager is up-to-date. */
+ if( maChangesListeners.getLength() > 0 )
+ {
+ ChangesEvent aEvent;
+ aEvent.Source = mpxEventSource;
+ aEvent.Base <<= aEvent.Source;
+ aEvent.Changes = { { Any(aName),
+ {}, // Element remains empty (meaning "replaced with nothing")
+ aOldElement } };
+ maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent );
+ }
+}
+
+
+// Methods XContainer
+void SAL_CALL NameContainer::addContainerListener( const Reference< XContainerListener >& xListener )
+{
+ if( !xListener.is() )
+ {
+ throw RuntimeException("addContainerListener called with null xListener",static_cast< cppu::OWeakObject * >(this));
+ }
+ maContainerListeners.addInterface( xListener );
+}
+
+void SAL_CALL NameContainer::removeContainerListener( const Reference< XContainerListener >& xListener )
+{
+ if( !xListener.is() )
+ {
+ throw RuntimeException("removeContainerListener called with null xListener",static_cast< cppu::OWeakObject * >(this));
+ }
+ maContainerListeners.removeInterface( xListener );
+}
+
+// Methods XChangesNotifier
+void SAL_CALL NameContainer::addChangesListener( const Reference< XChangesListener >& xListener )
+{
+ if( !xListener.is() )
+ {
+ throw RuntimeException("addChangesListener called with null xListener",static_cast< cppu::OWeakObject * >(this));
+ }
+ maChangesListeners.addInterface( xListener );
+}
+
+void SAL_CALL NameContainer::removeChangesListener( const Reference< XChangesListener >& xListener )
+{
+ if( !xListener.is() )
+ {
+ throw RuntimeException("removeChangesListener called with null xListener",static_cast< cppu::OWeakObject * >(this));
+ }
+ maChangesListeners.removeInterface( xListener );
+}
+
+
+// ModifiableHelper
+
+void ModifiableHelper::setModified( bool _bModified )
+{
+ if ( _bModified == mbModified )
+ {
+ return;
+ }
+ mbModified = _bModified;
+
+ if ( m_aModifyListeners.getLength() == 0 )
+ {
+ return;
+ }
+ EventObject aModifyEvent( m_rEventSource );
+ m_aModifyListeners.notifyEach( &XModifyListener::modified, aModifyEvent );
+}
+
+
+// Ctor
+SfxLibraryContainer::SfxLibraryContainer()
+ : SfxLibraryContainer_BASE( m_aMutex )
+ , maVBAScriptListeners( m_aMutex )
+ , mnRunningVBAScripts( 0 )
+ , mbVBACompat( false )
+ , meVBATextEncoding( RTL_TEXTENCODING_DONTKNOW )
+ , maModifiable( *this, m_aMutex )
+ , maNameContainer( new NameContainer(cppu::UnoType<XNameAccess>::get()) )
+ , mbOldInfoFormat( false )
+ , mbOasis2OOoFormat( false )
+ , mpBasMgr( nullptr )
+ , mbOwnBasMgr( false )
+ , meInitMode(DEFAULT)
+{
+ mxContext = comphelper::getProcessComponentContext();
+
+ mxSFI = ucb::SimpleFileAccess::create( mxContext );
+
+ mxStringSubstitution = util::PathSubstitution::create( mxContext );
+}
+
+SfxLibraryContainer::~SfxLibraryContainer()
+{
+ if( mbOwnBasMgr )
+ {
+ delete mpBasMgr;
+ }
+}
+
+void SfxLibraryContainer::enterMethod()
+{
+ Application::GetSolarMutex().acquire();
+ if ( rBHelper.bInDispose || rBHelper.bDisposed )
+ {
+ throw DisposedException( OUString(), *this );
+ }
+}
+
+void SfxLibraryContainer::leaveMethod()
+{
+ Application::GetSolarMutex().release();
+}
+
+BasicManager* SfxLibraryContainer::getBasicManager()
+{
+ try
+ {
+ if ( mpBasMgr )
+ {
+ return mpBasMgr;
+ }
+ Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY );
+ SAL_WARN_IF(
+ !xDocument.is(), "basic",
+ ("SfxLibraryContainer::getBasicManager: cannot obtain a BasicManager"
+ " without document!"));
+ if ( xDocument.is() )
+ {
+ mpBasMgr = BasicManagerRepository::getDocumentBasicManager( xDocument );
+ }
+ }
+ catch (const css::ucb::ContentCreationException&)
+ {
+ TOOLS_WARN_EXCEPTION( "basic", "SfxLibraryContainer::getBasicManager:" );
+ }
+ return mpBasMgr;
+}
+
+// Methods XStorageBasedLibraryContainer
+Reference< XStorage > SAL_CALL SfxLibraryContainer::getRootStorage()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return mxStorage;
+}
+
+void SAL_CALL SfxLibraryContainer::setRootStorage( const Reference< XStorage >& _rxRootStorage )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ if ( !_rxRootStorage.is() )
+ {
+ throw IllegalArgumentException("no root storage", static_cast<cppu::OWeakObject*>(this), 1);
+ }
+ mxStorage = _rxRootStorage;
+ onNewRootStorage();
+}
+
+void SAL_CALL SfxLibraryContainer::storeLibrariesToStorage( const Reference< XStorage >& _rxRootStorage )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ if ( !_rxRootStorage.is() )
+ {
+ throw IllegalArgumentException("no root storage", static_cast<cppu::OWeakObject*>(this), 1);
+ }
+ try
+ {
+ storeLibraries_Impl( _rxRootStorage, true );
+ }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException( OUString(),
+ *this, ::cppu::getCaughtException() );
+ }
+}
+
+
+// Methods XModifiable
+sal_Bool SfxLibraryContainer::isModified()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ if ( maModifiable.isModified() )
+ {
+ return true;
+ }
+ // the library container is not modified, go through the libraries and check whether they are modified
+ Sequence< OUString > aNames = maNameContainer->getElementNames();
+ const OUString* pNames = aNames.getConstArray();
+ sal_Int32 nNameCount = aNames.getLength();
+
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aName = pNames[ i ];
+ try
+ {
+ SfxLibrary* pImplLib = getImplLib( aName );
+ if( pImplLib->isModified() )
+ {
+ if ( aName == "Standard" )
+ {
+ // this is a workaround that has to be implemented because
+ // empty standard library should stay marked as modified
+ // but should not be treated as modified while it is empty
+ if ( pImplLib->hasElements() )
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ }
+ }
+
+ return false;
+}
+
+void SAL_CALL SfxLibraryContainer::setModified( sal_Bool _bModified )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ maModifiable.setModified( _bModified );
+}
+
+void SAL_CALL SfxLibraryContainer::addModifyListener( const Reference< XModifyListener >& _rxListener )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ maModifiable.addModifyListener( _rxListener );
+}
+
+void SAL_CALL SfxLibraryContainer::removeModifyListener( const Reference< XModifyListener >& _rxListener )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ maModifiable.removeModifyListener( _rxListener );
+}
+
+// Methods XPersistentLibraryContainer
+Any SAL_CALL SfxLibraryContainer::getRootLocation()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return Any( getRootStorage() );
+}
+
+OUString SAL_CALL SfxLibraryContainer::getContainerLocationName()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return maLibrariesDir;
+}
+
+void SAL_CALL SfxLibraryContainer::storeLibraries( )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ try
+ {
+ storeLibraries_Impl( mxStorage, mxStorage.is() );
+ // we need to store *all* libraries if and only if we are based on a storage:
+ // in this case, storeLibraries_Impl will remove the source storage, after loading
+ // all libraries, so we need to force them to be stored, again
+ }
+ catch( const Exception& )
+ {
+ throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
+ }
+}
+
+static void checkAndCopyFileImpl( const INetURLObject& rSourceFolderInetObj,
+ const INetURLObject& rTargetFolderInetObj,
+ std::u16string_view rCheckFileName,
+ std::u16string_view rCheckExtension,
+ const Reference< XSimpleFileAccess3 >& xSFI )
+{
+ INetURLObject aTargetFolderInetObj( rTargetFolderInetObj );
+ aTargetFolderInetObj.insertName( rCheckFileName, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aTargetFolderInetObj.setExtension( rCheckExtension );
+ OUString aTargetFile = aTargetFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( !xSFI->exists( aTargetFile ) )
+ {
+ INetURLObject aSourceFolderInetObj( rSourceFolderInetObj );
+ aSourceFolderInetObj.insertName( rCheckFileName, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aSourceFolderInetObj.setExtension( rCheckExtension );
+ OUString aSourceFile = aSourceFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ xSFI->copy( aSourceFile, aTargetFile );
+ }
+}
+
+static void createVariableURL( OUString& rStr, std::u16string_view rLibName,
+ std::u16string_view rInfoFileName, bool bUser )
+{
+ if( bUser )
+ {
+ rStr = "$(USER)/basic/";
+ }
+ else
+ {
+ rStr = "$(INST)/" LIBO_SHARE_FOLDER "/basic/";
+ }
+ rStr += OUString::Concat(rLibName) + "/" + rInfoFileName + ".xlb/";
+}
+
+void SfxLibraryContainer::init( const OUString& rInitialDocumentURL, const uno::Reference< embed::XStorage >& rxInitialStorage )
+{
+ // this might be called from within the ctor, and the impl_init might (indirectly) create
+ // a UNO reference to ourself.
+ // Ensure that we're not destroyed while we're in here
+ osl_atomic_increment( &m_refCount );
+ init_Impl( rInitialDocumentURL, rxInitialStorage );
+ osl_atomic_decrement( &m_refCount );
+}
+
+void SfxLibraryContainer::init_Impl( const OUString& rInitialDocumentURL,
+ const uno::Reference< embed::XStorage >& rxInitialStorage )
+{
+ uno::Reference< embed::XStorage > xStorage = rxInitialStorage;
+
+ maInitialDocumentURL = rInitialDocumentURL;
+ maInfoFileName = getInfoFileName();
+ maOldInfoFileName = getOldInfoFileName();
+ maLibElementFileExtension = getLibElementFileExtension();
+ maLibrariesDir = getLibrariesDir();
+
+ meInitMode = DEFAULT;
+ INetURLObject aInitUrlInetObj( maInitialDocumentURL );
+ OUString aInitFileName = aInitUrlInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( !aInitFileName.isEmpty() )
+ {
+ // We need a BasicManager to avoid problems
+ StarBASIC* pBas = new StarBASIC();
+ mpBasMgr = new BasicManager( pBas );
+ mbOwnBasMgr = true;
+
+ OUString aExtension = aInitUrlInetObj.getExtension();
+ if( aExtension == "xlc" )
+ {
+ meInitMode = CONTAINER_INIT_FILE;
+ INetURLObject aLibPathInetObj( aInitUrlInetObj );
+ aLibPathInetObj.removeSegment();
+ maLibraryPath = aLibPathInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ else if( aExtension == "xlb" )
+ {
+ meInitMode = LIBRARY_INIT_FILE;
+ uno::Reference< embed::XStorage > xDummyStor;
+ ::xmlscript::LibDescriptor aLibDesc;
+ implLoadLibraryIndexFile( nullptr, aLibDesc, xDummyStor, aInitFileName );
+ return;
+ }
+ else
+ {
+ // Decide between old and new document
+ bool bOldStorage = SotStorage::IsOLEStorage( aInitFileName );
+ if ( bOldStorage )
+ {
+ meInitMode = OLD_BASIC_STORAGE;
+ importFromOldStorage( aInitFileName );
+ return;
+ }
+ else
+ {
+ meInitMode = OFFICE_DOCUMENT;
+ try
+ {
+ xStorage = ::comphelper::OStorageHelper::GetStorageFromURL( aInitFileName, embed::ElementModes::READ );
+ }
+ catch (const uno::Exception& )
+ {
+ // TODO: error handling
+ }
+ }
+ }
+ }
+ else
+ {
+ // Default paths
+ maLibraryPath = SvtPathOptions().GetBasicPath();
+ }
+
+ uno::Reference< io::XInputStream > xInput;
+
+ mxStorage = xStorage;
+ bool bStorage = mxStorage.is();
+
+
+ // #110009: Scope to force the StorageRefs to be destructed and
+ // so the streams to be closed before the preload operation
+ {
+
+ uno::Reference< embed::XStorage > xLibrariesStor;
+ OUString aFileName;
+
+ int nPassCount = 1;
+ if( !bStorage && meInitMode == DEFAULT )
+ {
+ nPassCount = 2;
+ }
+ for( int nPass = 0 ; nPass < nPassCount ; nPass++ )
+ {
+ if( bStorage )
+ {
+ SAL_WARN_IF(
+ meInitMode != DEFAULT && meInitMode != OFFICE_DOCUMENT, "basic",
+ "Wrong InitMode for document");
+ try
+ {
+ uno::Reference< io::XStream > xStream;
+ xLibrariesStor = xStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
+
+ if ( xLibrariesStor.is() )
+ {
+ aFileName = maInfoFileName + "-lc.xml";
+ try
+ {
+ xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
+ }
+ catch(const uno::Exception& )
+ {}
+
+ if( !xStream.is() )
+ {
+ mbOldInfoFormat = true;
+
+ // Check old version
+ aFileName = maOldInfoFileName + ".xml";
+ try
+ {
+ xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
+ }
+ catch(const uno::Exception& )
+ {}
+
+ if( !xStream.is() )
+ {
+ // Check for EA2 document version with wrong extensions
+ aFileName = maOldInfoFileName + ".xli";
+ xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
+ }
+ }
+ }
+
+ if ( xStream.is() )
+ {
+ xInput = xStream->getInputStream();
+ }
+ }
+ catch(const uno::Exception& )
+ {
+ // TODO: error handling?
+ }
+ }
+ else
+ {
+ std::unique_ptr<INetURLObject> pLibInfoInetObj;
+ if( meInitMode == CONTAINER_INIT_FILE )
+ {
+ aFileName = aInitFileName;
+ }
+ else
+ {
+ if( nPass == 1 )
+ {
+ pLibInfoInetObj.reset(new INetURLObject( o3tl::getToken(maLibraryPath, 0, ';') ));
+ }
+ else
+ {
+ pLibInfoInetObj.reset(new INetURLObject( o3tl::getToken(maLibraryPath, 1, ';') ));
+ }
+ pLibInfoInetObj->insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ pLibInfoInetObj->setExtension( u"xlc" );
+ aFileName = pLibInfoInetObj->GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ try
+ {
+ xInput = mxSFI->openFileRead( aFileName );
+ }
+ catch(const Exception& )
+ {
+ // Silently tolerate empty or missing files
+ xInput.clear();
+ }
+
+ // Old variant?
+ if( !xInput.is() && nPass == 0 )
+ {
+ INetURLObject aLibInfoInetObj( o3tl::getToken(maLibraryPath, 1, ';') );
+ aLibInfoInetObj.insertName( maOldInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ aLibInfoInetObj.setExtension( u"xli" );
+ aFileName = aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ try
+ {
+ xInput = mxSFI->openFileRead( aFileName );
+ mbOldInfoFormat = true;
+ }
+ catch(const Exception& )
+ {
+ xInput.clear();
+ }
+ }
+ }
+
+ if( xInput.is() )
+ {
+ InputSource source;
+ source.aInputStream = xInput;
+ source.sSystemId = aFileName;
+
+ // start parsing
+ auto pLibArray = std::make_unique<::xmlscript::LibDescriptorArray> ( );
+
+ Reference< XParser > xParser = xml::sax::Parser::create(mxContext);
+ try
+ {
+ xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( pLibArray.get() ) );
+ xParser->parseStream( source );
+ }
+ catch ( const xml::sax::SAXException& )
+ {
+ TOOLS_WARN_EXCEPTION( "basic", "" );
+ return;
+ }
+ catch ( const io::IOException& )
+ {
+ TOOLS_WARN_EXCEPTION( "basic", "" );
+ return;
+ }
+
+ sal_Int32 nLibCount = pLibArray->mnLibCount;
+ for( sal_Int32 i = 0 ; i < nLibCount ; i++ )
+ {
+ ::xmlscript::LibDescriptor& rLib = pLibArray->mpLibs[i];
+
+ // Check storage URL
+ OUString aStorageURL = rLib.aStorageURL;
+ if( !bStorage && aStorageURL.isEmpty() && nPass == 0 )
+ {
+ OUString aLibraryPath;
+ if( meInitMode == CONTAINER_INIT_FILE )
+ {
+ aLibraryPath = maLibraryPath;
+ }
+ else
+ {
+ aLibraryPath = maLibraryPath.getToken(1, ';');
+ }
+ INetURLObject aInetObj( aLibraryPath );
+
+ aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( mxSFI->isFolder( aLibDirPath ) )
+ {
+ createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, true );
+ maModifiable.setModified( true );
+ }
+ else if( rLib.bLink )
+ {
+ // Check "share" path
+ INetURLObject aShareInetObj( o3tl::getToken(maLibraryPath, 0, ';') );
+ aShareInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ OUString aShareLibDirPath = aShareInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( mxSFI->isFolder( aShareLibDirPath ) )
+ {
+ createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, false );
+ maModifiable.setModified( true );
+ }
+ else
+ {
+ // #i25537: Ignore lib if library folder does not really exist
+ continue;
+ }
+ }
+ }
+
+ OUString aLibName = rLib.aName;
+
+ // If the same library name is used by the shared and the
+ // user lib container index files the user file wins
+ if( nPass == 1 && hasByName( aLibName ) )
+ {
+ continue;
+ }
+ SfxLibrary* pImplLib;
+ if( rLib.bLink )
+ {
+ Reference< XNameAccess > xLib =
+ createLibraryLink( aLibName, rLib.aStorageURL, rLib.bReadOnly );
+ pImplLib = static_cast< SfxLibrary* >( xLib.get() );
+ }
+ else
+ {
+ Reference< XNameContainer > xLib = createLibrary( aLibName );
+ pImplLib = static_cast< SfxLibrary* >( xLib.get() );
+ pImplLib->mbLoaded = false;
+ pImplLib->mbReadOnly = rLib.bReadOnly;
+ if( !bStorage )
+ {
+ checkStorageURL( rLib.aStorageURL, pImplLib->maLibInfoFileURL,
+ pImplLib->maStorageURL, pImplLib->maUnexpandedStorageURL );
+ }
+ }
+ maModifiable.setModified( false );
+
+ // Read library info files
+ if( !mbOldInfoFormat )
+ {
+ uno::Reference< embed::XStorage > xLibraryStor;
+ if( !pImplLib->mbInitialised && bStorage )
+ {
+ try
+ {
+ xLibraryStor = xLibrariesStor->openStorageElement( rLib.aName,
+ embed::ElementModes::READ );
+ }
+ catch(const uno::Exception& )
+ {
+ #if OSL_DEBUG_LEVEL > 0
+ TOOLS_WARN_EXCEPTION(
+ "basic",
+ "couldn't open sub storage for library \"" << rLib.aName << "\"");
+ #endif
+ }
+ }
+
+ // Link is already initialised in createLibraryLink()
+ if( !pImplLib->mbInitialised && (!bStorage || xLibraryStor.is()) )
+ {
+ bool bLoaded = implLoadLibraryIndexFile( pImplLib, rLib, xLibraryStor, OUString() );
+ SAL_WARN_IF(
+ bLoaded && aLibName != rLib.aName, "basic",
+ ("Different library names in library container and"
+ " library info files!"));
+ if( GbMigrationSuppressErrors && !bLoaded )
+ {
+ removeLibrary( aLibName );
+ }
+ }
+ }
+ else if( !bStorage )
+ {
+ // Write new index file immediately because otherwise
+ // the library elements will be lost when storing into
+ // the new info format
+ uno::Reference< embed::XStorage > xTmpStorage;
+ implStoreLibraryIndexFile( pImplLib, rLib, xTmpStorage );
+ }
+
+ implImportLibDescriptor( pImplLib, rLib );
+
+ if( nPass == 1 )
+ {
+ pImplLib->mbSharedIndexFile = true;
+ pImplLib->mbReadOnly = true;
+ }
+ }
+
+ // Keep flag for documents to force writing the new index files
+ if( !bStorage )
+ {
+ mbOldInfoFormat = false;
+ }
+ }
+ }
+
+ // #110009: END Scope to force the StorageRefs to be destructed
+ }
+
+ if( !bStorage && meInitMode == DEFAULT )
+ {
+ try
+ {
+ implScanExtensions();
+ }
+ catch(const uno::Exception& )
+ {
+ // TODO: error handling?
+ SAL_WARN("basic", "Cannot access extensions!");
+ }
+ }
+
+ // Preload?
+ {
+ Sequence< OUString > aNames = maNameContainer->getElementNames();
+ const OUString* pNames = aNames.getConstArray();
+ sal_Int32 nNameCount = aNames.getLength();
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aName = pNames[ i ];
+ SfxLibrary* pImplLib = getImplLib( aName );
+ if( pImplLib->mbPreload )
+ {
+ loadLibrary( aName );
+ }
+ }
+ }
+
+ if( meInitMode != DEFAULT )
+ return;
+
+ // tdf#121740 speed up loading documents with lots of embedded documents by avoid the UCB work of updating non-existent VBA libraries
+ if (rInitialDocumentURL.isEmpty())
+ return;
+
+ INetURLObject aUserBasicInetObj( o3tl::getToken(maLibraryPath, 1, ';') );
+ OUString aStandardStr("Standard");
+
+ INetURLObject aPrevUserBasicInetObj_1( aUserBasicInetObj );
+ aPrevUserBasicInetObj_1.removeSegment();
+ INetURLObject aPrevUserBasicInetObj_2 = aPrevUserBasicInetObj_1;
+ aPrevUserBasicInetObj_1.Append( u"__basic_80" );
+ aPrevUserBasicInetObj_2.Append( u"__basic_80_2" );
+
+ // #i93163
+ bool bCleanUp = false;
+ try
+ {
+ INetURLObject aPrevUserBasicInetObj = aPrevUserBasicInetObj_1;
+ OUString aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( mxSFI->isFolder( aPrevFolder ) )
+ {
+ // Check if Standard folder exists and is complete
+ INetURLObject aUserBasicStandardInetObj( aUserBasicInetObj );
+ aUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ INetURLObject aPrevUserBasicStandardInetObj( aPrevUserBasicInetObj );
+ aPrevUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ OUString aPrevStandardFolder = aPrevUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( mxSFI->isFolder( aPrevStandardFolder ) )
+ {
+ OUString aXlbExtension( "xlb" );
+ OUString aCheckFileName;
+
+ // Check if script.xlb exists
+ aCheckFileName = "script";
+ checkAndCopyFileImpl( aUserBasicStandardInetObj,
+ aPrevUserBasicStandardInetObj,
+ aCheckFileName, aXlbExtension, mxSFI );
+
+ // Check if dialog.xlb exists
+ aCheckFileName = "dialog";
+ checkAndCopyFileImpl( aUserBasicStandardInetObj,
+ aPrevUserBasicStandardInetObj,
+ aCheckFileName, aXlbExtension, mxSFI );
+
+ // Check if module1.xba exists
+ aCheckFileName = "Module1";
+ checkAndCopyFileImpl( aUserBasicStandardInetObj,
+ aPrevUserBasicStandardInetObj,
+ aCheckFileName, u"xba", mxSFI );
+ }
+ else
+ {
+ OUString aStandardFolder = aUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ mxSFI->copy( aStandardFolder, aPrevStandardFolder );
+ }
+
+ OUString aPrevCopyToFolder = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ mxSFI->copy( aPrevFolder, aPrevCopyToFolder );
+ }
+ else
+ {
+ aPrevUserBasicInetObj = aPrevUserBasicInetObj_2;
+ aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ if( mxSFI->isFolder( aPrevFolder ) )
+ {
+ rtl::Reference<SfxLibraryContainer> pPrevCont = createInstanceImpl();
+
+ // Rename previous basic folder to make storage URLs correct during initialisation
+ OUString aFolderUserBasic = aUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ INetURLObject aUserBasicTmpInetObj( aUserBasicInetObj );
+ aUserBasicTmpInetObj.removeSegment();
+ aUserBasicTmpInetObj.Append( u"__basic_tmp" );
+ OUString aFolderTmp = aUserBasicTmpInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ mxSFI->move( aFolderUserBasic, aFolderTmp );
+ try
+ {
+ mxSFI->move( aPrevFolder, aFolderUserBasic );
+ }
+ catch(const Exception& )
+ {
+ // Move back user/basic folder
+ try
+ {
+ mxSFI->kill( aFolderUserBasic );
+ }
+ catch(const Exception& )
+ {}
+ mxSFI->move( aFolderTmp, aFolderUserBasic );
+ throw;
+ }
+
+ INetURLObject aPrevUserBasicLibInfoInetObj( aUserBasicInetObj );
+ aPrevUserBasicLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aPrevUserBasicLibInfoInetObj.setExtension( u"xlc");
+ OUString aLibInfoFileName = aPrevUserBasicLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ Sequence<Any> aInitSeq( 1 );
+ aInitSeq.getArray()[0] <<= aLibInfoFileName;
+ GbMigrationSuppressErrors = true;
+ pPrevCont->initialize( aInitSeq );
+ GbMigrationSuppressErrors = false;
+
+ // Rename folders back
+ mxSFI->move( aFolderUserBasic, aPrevFolder );
+ mxSFI->move( aFolderTmp, aFolderUserBasic );
+
+ Sequence< OUString > aNames = pPrevCont->getElementNames();
+ const OUString* pNames = aNames.getConstArray();
+ sal_Int32 nNameCount = aNames.getLength();
+
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aLibName = pNames[ i ];
+ if( hasByName( aLibName ) )
+ {
+ if( aLibName == aStandardStr )
+ {
+ SfxLibrary* pImplLib = getImplLib( aStandardStr );
+ OUString aStandardFolder = pImplLib->maStorageURL;
+ mxSFI->kill( aStandardFolder );
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ SfxLibrary* pImplLib = pPrevCont->getImplLib( aLibName );
+ if( pImplLib->mbLink )
+ {
+ OUString aStorageURL = pImplLib->maUnexpandedStorageURL;
+ bool bCreateLink = true;
+ if( aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 ||
+ aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1 ||
+ aStorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 ||
+ aStorageURL.indexOf( "$(INST)" ) != -1 )
+ {
+ bCreateLink = false;
+ }
+ if( bCreateLink )
+ {
+ createLibraryLink( aLibName, pImplLib->maStorageURL, pImplLib->mbReadOnly );
+ }
+ }
+ else
+ {
+ // Move folder if not already done
+ INetURLObject aUserBasicLibFolderInetObj( aUserBasicInetObj );
+ aUserBasicLibFolderInetObj.Append( aLibName );
+ OUString aLibFolder = aUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ INetURLObject aPrevUserBasicLibFolderInetObj( aPrevUserBasicInetObj );
+ aPrevUserBasicLibFolderInetObj.Append( aLibName );
+ OUString aPrevLibFolder = aPrevUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ if( mxSFI->isFolder( aPrevLibFolder ) && !mxSFI->isFolder( aLibFolder ) )
+ {
+ mxSFI->move( aPrevLibFolder, aLibFolder );
+ }
+
+ if( aLibName == aStandardStr )
+ {
+ maNameContainer->removeByName( aLibName );
+ }
+
+ // Create library
+ Reference< XNameContainer > xLib = createLibrary( aLibName );
+ SfxLibrary* pNewLib = static_cast< SfxLibrary* >( xLib.get() );
+ pNewLib->mbLoaded = false;
+ pNewLib->implSetModified( false );
+ checkStorageURL( aLibFolder, pNewLib->maLibInfoFileURL,
+ pNewLib->maStorageURL, pNewLib->maUnexpandedStorageURL );
+
+ uno::Reference< embed::XStorage > xDummyStor;
+ ::xmlscript::LibDescriptor aLibDesc;
+ implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, pNewLib->maLibInfoFileURL );
+ implImportLibDescriptor( pNewLib, aLibDesc );
+ }
+ }
+ mxSFI->kill( aPrevFolder );
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("basic", "Upgrade of Basic installation failed somehow" );
+ bCleanUp = true;
+ }
+
+ // #i93163
+ if( !bCleanUp )
+ return;
+
+ INetURLObject aPrevUserBasicInetObj_Err( aUserBasicInetObj );
+ aPrevUserBasicInetObj_Err.removeSegment();
+ aPrevUserBasicInetObj_Err.Append( u"__basic_80_err" );
+ OUString aPrevFolder_Err = aPrevUserBasicInetObj_Err.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ bool bSaved = false;
+ try
+ {
+ OUString aPrevFolder_1 = aPrevUserBasicInetObj_1.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( mxSFI->isFolder( aPrevFolder_1 ) )
+ {
+ mxSFI->move( aPrevFolder_1, aPrevFolder_Err );
+ bSaved = true;
+ }
+ }
+ catch(const Exception& )
+ {}
+ try
+ {
+ OUString aPrevFolder_2 = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( !bSaved && mxSFI->isFolder( aPrevFolder_2 ) )
+ {
+ mxSFI->move( aPrevFolder_2, aPrevFolder_Err );
+ }
+ else
+ {
+ mxSFI->kill( aPrevFolder_2 );
+ }
+ }
+ catch(const Exception& )
+ {}
+}
+
+void SfxLibraryContainer::implScanExtensions()
+{
+#if HAVE_FEATURE_EXTENSIONS
+ ScriptExtensionIterator aScriptIt;
+
+ bool bPureDialogLib = false;
+ for (;;)
+ {
+ OUString aLibURL = aScriptIt.nextBasicOrDialogLibrary( bPureDialogLib );
+ if (aLibURL.isEmpty())
+ break;
+ if( bPureDialogLib && maInfoFileName == "script" )
+ {
+ continue;
+ }
+ // Extract lib name
+ sal_Int32 nLen = aLibURL.getLength();
+ sal_Int32 indexLastSlash = aLibURL.lastIndexOf( '/' );
+ sal_Int32 nReduceCopy = 0;
+ if( indexLastSlash == nLen - 1 )
+ {
+ nReduceCopy = 1;
+ indexLastSlash = aLibURL.lastIndexOf( '/', nLen - 1 );
+ }
+
+ OUString aLibName = aLibURL.copy( indexLastSlash + 1, nLen - indexLastSlash - nReduceCopy - 1 );
+
+ // If a library of the same exists the existing library wins
+ if( hasByName( aLibName ) )
+ {
+ continue;
+ }
+ // Add index file to URL
+ OUString aIndexFileURL = aLibURL;
+ if( nReduceCopy == 0 )
+ {
+ aIndexFileURL += "/";
+ }
+ aIndexFileURL += maInfoFileName + ".xlb";
+
+ // Create link
+ const bool bReadOnly = false;
+ createLibraryLink( aLibName, aIndexFileURL, bReadOnly );
+ }
+#else
+ (void) this;
+#endif
+}
+
+// Handle maLibInfoFileURL and maStorageURL correctly
+void SfxLibraryContainer::checkStorageURL( const OUString& aSourceURL,
+ OUString& aLibInfoFileURL, OUString& aStorageURL,
+ OUString& aUnexpandedStorageURL )
+{
+ OUString aExpandedSourceURL = expand_url( aSourceURL );
+ if( aExpandedSourceURL != aSourceURL )
+ {
+ aUnexpandedStorageURL = aSourceURL;
+ }
+ INetURLObject aInetObj( aExpandedSourceURL );
+ OUString aExtension = aInetObj.getExtension();
+ if( aExtension == "xlb" )
+ {
+ // URL to xlb file
+ aLibInfoFileURL = aExpandedSourceURL;
+ aInetObj.removeSegment();
+ aStorageURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ else
+ {
+ // URL to library folder
+ aStorageURL = aExpandedSourceURL;
+ aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ aInetObj.setExtension( u"xlb" );
+ aLibInfoFileURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+}
+
+SfxLibrary* SfxLibraryContainer::getImplLib( const OUString& rLibraryName )
+{
+ Any aLibAny = maNameContainer->getByName( rLibraryName ) ;
+ Reference< XNameAccess > xNameAccess;
+ aLibAny >>= xNameAccess;
+ SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
+ return pImplLib;
+}
+
+
+// Storing with password encryption
+
+// Empty implementation, avoids unnecessary implementation in dlgcont.cxx
+bool SfxLibraryContainer::implStorePasswordLibrary( SfxLibrary*,
+ const OUString&,
+ const uno::Reference< embed::XStorage >&,
+ const uno::Reference< task::XInteractionHandler >& )
+{
+ return false;
+}
+
+bool SfxLibraryContainer::implStorePasswordLibrary(
+ SfxLibrary* /*pLib*/,
+ const OUString& /*aName*/,
+ const css::uno::Reference< css::embed::XStorage >& /*xStorage*/,
+ const OUString& /*aTargetURL*/,
+ const Reference< XSimpleFileAccess3 >& /*xToUseSFI*/,
+ const uno::Reference< task::XInteractionHandler >& )
+{
+ return false;
+}
+
+bool SfxLibraryContainer::implLoadPasswordLibrary(
+ SfxLibrary* /*pLib*/,
+ const OUString& /*Name*/,
+ bool /*bVerifyPasswordOnly*/ )
+{
+ return true;
+}
+
+OUString SfxLibraryContainer::createAppLibraryFolder( SfxLibrary* pLib, std::u16string_view aName )
+{
+ OUString aLibDirPath = pLib->maStorageURL;
+ if( aLibDirPath.isEmpty() )
+ {
+ INetURLObject aInetObj( o3tl::getToken(maLibraryPath, 1, ';') );
+ aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ checkStorageURL( aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), pLib->maLibInfoFileURL,
+ pLib->maStorageURL, pLib->maUnexpandedStorageURL );
+ aLibDirPath = pLib->maStorageURL;
+ }
+
+ if( !mxSFI->isFolder( aLibDirPath ) )
+ {
+ try
+ {
+ mxSFI->createFolder( aLibDirPath );
+ }
+ catch(const Exception& )
+ {}
+ }
+
+ return aLibDirPath;
+}
+
+// Storing
+void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib,
+ std::u16string_view aName,
+ const uno::Reference< embed::XStorage >& xStorage )
+{
+ Reference< XSimpleFileAccess3 > xDummySFA;
+ Reference< XInteractionHandler > xDummyHandler;
+ implStoreLibrary( pLib, aName, xStorage, u"", xDummySFA, xDummyHandler );
+}
+
+// New variant for library export
+void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib,
+ std::u16string_view aName,
+ const uno::Reference< embed::XStorage >& xStorage,
+ std::u16string_view aTargetURL,
+ const Reference< XSimpleFileAccess3 >& rToUseSFI,
+ const Reference< XInteractionHandler >& xHandler )
+{
+ bool bLink = pLib->mbLink;
+ bool bStorage = xStorage.is() && !bLink;
+
+ Sequence< OUString > aElementNames = pLib->getElementNames();
+ sal_Int32 nNameCount = aElementNames.getLength();
+ const OUString* pNames = aElementNames.getConstArray();
+
+ if( bStorage )
+ {
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aElementName = pNames[ i ];
+ OUString aStreamName = aElementName + ".xml";
+
+ if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
+ {
+ SAL_WARN(
+ "basic",
+ "invalid library element \"" << aElementName << '"');
+ continue;
+ }
+ try
+ {
+ uno::Reference< io::XStream > xElementStream = xStorage->openStreamElement(
+ aStreamName,
+ embed::ElementModes::READWRITE );
+ // throw uno::RuntimeException(); // TODO: method must either return the stream or throw an exception
+
+ uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
+ SAL_WARN_IF(
+ !xProps.is(), "basic",
+ "The StorageStream must implement XPropertySet interface!");
+ //if ( !xProps.is() ) //TODO
+
+ if ( xProps.is() )
+ {
+ xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
+
+ // #87671 Allow encryption
+ xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
+
+ Reference< XOutputStream > xOutput = xElementStream->getOutputStream();
+ Reference< XNameContainer > xLib( pLib );
+ writeLibraryElement( xLib, aElementName, xOutput );
+ }
+ }
+ catch(const uno::Exception& )
+ {
+ SAL_WARN("basic", "Problem during storing of library!");
+ // TODO: error handling?
+ }
+ }
+ pLib->storeResourcesToStorage( xStorage );
+ }
+ else
+ {
+ // Export?
+ bool bExport = !aTargetURL.empty();
+ try
+ {
+ Reference< XSimpleFileAccess3 > xSFI = mxSFI;
+ if( rToUseSFI.is() )
+ {
+ xSFI = rToUseSFI;
+ }
+ OUString aLibDirPath;
+ if( bExport )
+ {
+ INetURLObject aInetObj( aTargetURL );
+ aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ if( !xSFI->isFolder( aLibDirPath ) )
+ {
+ xSFI->createFolder( aLibDirPath );
+ }
+ pLib->storeResourcesToURL( aLibDirPath, xHandler );
+ }
+ else
+ {
+ aLibDirPath = createAppLibraryFolder( pLib, aName );
+ pLib->storeResources();
+ }
+
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aElementName = pNames[ i ];
+
+ INetURLObject aElementInetObj( aLibDirPath );
+ aElementInetObj.insertName( aElementName, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aElementInetObj.setExtension( maLibElementFileExtension );
+ OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
+ {
+ SAL_WARN(
+ "basic",
+ "invalid library element \"" << aElementName << '"');
+ continue;
+ }
+
+ // TODO: Check modified
+ try
+ {
+ if( xSFI->exists( aElementPath ) )
+ {
+ xSFI->kill( aElementPath );
+ }
+ Reference< XOutputStream > xOutput = xSFI->openFileWrite( aElementPath );
+ Reference< XNameContainer > xLib( pLib );
+ writeLibraryElement( xLib, aElementName, xOutput );
+ xOutput->closeOutput();
+ }
+ catch(const Exception& )
+ {
+ if( bExport )
+ {
+ throw;
+ }
+ SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aElementPath );
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ catch(const Exception& )
+ {
+ if( bExport )
+ {
+ throw;
+ }
+ }
+ }
+}
+
+void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib,
+ const ::xmlscript::LibDescriptor& rLib,
+ const uno::Reference< embed::XStorage >& xStorage )
+{
+ Reference< XSimpleFileAccess3 > xDummySFA;
+ implStoreLibraryIndexFile( pLib, rLib, xStorage, u"", xDummySFA );
+}
+
+// New variant for library export
+void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib,
+ const ::xmlscript::LibDescriptor& rLib,
+ const uno::Reference< embed::XStorage >& xStorage,
+ std::u16string_view aTargetURL,
+ const Reference< XSimpleFileAccess3 >& rToUseSFI )
+{
+ // Create sax writer
+ Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
+
+ bool bLink = pLib->mbLink;
+ bool bStorage = xStorage.is() && !bLink;
+
+ // Write info file
+ uno::Reference< io::XOutputStream > xOut;
+ uno::Reference< io::XStream > xInfoStream;
+ if( bStorage )
+ {
+ OUString aStreamName = maInfoFileName + "-lb.xml";
+
+ try
+ {
+ xInfoStream = xStorage->openStreamElement( aStreamName, embed::ElementModes::READWRITE );
+ SAL_WARN_IF(!xInfoStream.is(), "basic", "No stream!");
+ uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY );
+ // throw uno::RuntimeException(); // TODO
+
+ if ( xProps.is() )
+ {
+ xProps->setPropertyValue("MediaType", uno::Any( OUString("text/xml") ) );
+
+ // #87671 Allow encryption
+ xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
+
+ xOut = xInfoStream->getOutputStream();
+ }
+ }
+ catch(const uno::Exception& )
+ {
+ SAL_WARN("basic", "Problem during storing of library index file!");
+ // TODO: error handling?
+ }
+ }
+ else
+ {
+ // Export?
+ bool bExport = !aTargetURL.empty();
+ Reference< XSimpleFileAccess3 > xSFI = mxSFI;
+ if( rToUseSFI.is() )
+ {
+ xSFI = rToUseSFI;
+ }
+ OUString aLibInfoPath;
+ if( bExport )
+ {
+ INetURLObject aInetObj( aTargetURL );
+ aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ if( !xSFI->isFolder( aLibDirPath ) )
+ {
+ xSFI->createFolder( aLibDirPath );
+ }
+ aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ aInetObj.setExtension( u"xlb" );
+ aLibInfoPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ else
+ {
+ createAppLibraryFolder( pLib, rLib.aName );
+ aLibInfoPath = pLib->maLibInfoFileURL;
+ }
+
+ try
+ {
+ if( xSFI->exists( aLibInfoPath ) )
+ {
+ xSFI->kill( aLibInfoPath );
+ }
+ xOut = xSFI->openFileWrite( aLibInfoPath );
+ }
+ catch(const Exception& )
+ {
+ if( bExport )
+ {
+ throw;
+ }
+ SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath );
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+ }
+ if( !xOut.is() )
+ {
+ SAL_WARN("basic", "couldn't open output stream");
+ return;
+ }
+ xWriter->setOutputStream( xOut );
+ xmlscript::exportLibrary( xWriter, rLib );
+}
+
+
+bool SfxLibraryContainer::implLoadLibraryIndexFile( SfxLibrary* pLib,
+ ::xmlscript::LibDescriptor& rLib,
+ const uno::Reference< embed::XStorage >& xStorage,
+ const OUString& aIndexFileName )
+{
+ Reference< XParser > xParser = xml::sax::Parser::create(mxContext);
+
+ bool bStorage = false;
+ if( pLib )
+ {
+ bool bLink = pLib->mbLink;
+ bStorage = xStorage.is() && !bLink;
+ }
+
+ // Read info file
+ uno::Reference< io::XInputStream > xInput;
+ OUString aLibInfoPath;
+ if( bStorage )
+ {
+ aLibInfoPath = maInfoFileName + "-lb.xml";
+
+ try
+ {
+ uno::Reference< io::XStream > xInfoStream =
+ xStorage->openStreamElement( aLibInfoPath, embed::ElementModes::READ );
+ xInput = xInfoStream->getInputStream();
+ }
+ catch(const uno::Exception& )
+ {}
+ }
+ else
+ {
+ // Create Input stream
+ //String aLibInfoPath; // attention: THIS PROBLEM MUST BE REVIEWED BY SCRIPTING OWNER!!!
+
+ if( pLib )
+ {
+ createAppLibraryFolder( pLib, rLib.aName );
+ aLibInfoPath = pLib->maLibInfoFileURL;
+ }
+ else
+ {
+ aLibInfoPath = aIndexFileName;
+ }
+ try
+ {
+ xInput = mxSFI->openFileRead( aLibInfoPath );
+ }
+ catch(const Exception& )
+ {
+ xInput.clear();
+ if( !GbMigrationSuppressErrors )
+ {
+ SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath );
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ if( !xInput.is() )
+ {
+ return false;
+ }
+
+ InputSource source;
+ source.aInputStream = xInput;
+ source.sSystemId = aLibInfoPath;
+
+ // start parsing
+ try
+ {
+ xParser->setDocumentHandler( ::xmlscript::importLibrary( rLib ) );
+ xParser->parseStream( source );
+ }
+ catch(const Exception& )
+ {
+ SAL_WARN("basic", "Parsing error");
+ SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath );
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ return false;
+ }
+
+ if( !pLib )
+ {
+ Reference< XNameContainer > xLib = createLibrary( rLib.aName );
+ pLib = static_cast< SfxLibrary* >( xLib.get() );
+ pLib->mbLoaded = false;
+ rLib.aStorageURL = aIndexFileName;
+ checkStorageURL( rLib.aStorageURL, pLib->maLibInfoFileURL, pLib->maStorageURL,
+ pLib->maUnexpandedStorageURL );
+
+ implImportLibDescriptor( pLib, rLib );
+ }
+
+ return true;
+}
+
+void SfxLibraryContainer::implImportLibDescriptor( SfxLibrary* pLib,
+ ::xmlscript::LibDescriptor const & rLib )
+{
+ if( pLib->mbInitialised )
+ return;
+
+ sal_Int32 nElementCount = rLib.aElementNames.getLength();
+ const OUString* pElementNames = rLib.aElementNames.getConstArray();
+ Any aDummyElement = createEmptyLibraryElement();
+ for( sal_Int32 i = 0 ; i < nElementCount ; i++ )
+ {
+ pLib->maNameContainer->insertByName( pElementNames[i], aDummyElement );
+ }
+ pLib->mbPasswordProtected = rLib.bPasswordProtected;
+ pLib->mbReadOnly = rLib.bReadOnly;
+ pLib->mbPreload = rLib.bPreload;
+ pLib->implSetModified( false );
+ pLib->mbInitialised = true;
+}
+
+
+// Methods of new XLibraryStorage interface?
+void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference< embed::XStorage >& i_rStorage,
+ bool bComplete )
+{
+ const Sequence< OUString > aNames = maNameContainer->getElementNames();
+ const sal_Int32 nNameCount = aNames.getLength();
+ const OUString* pName = aNames.getConstArray();
+ const OUString* pNamesEnd = aNames.getConstArray() + nNameCount;
+
+ // Don't count libs from shared index file
+ sal_Int32 nLibsToSave = nNameCount;
+ for( ; pName != pNamesEnd; ++pName )
+ {
+ SfxLibrary* pImplLib = getImplLib( *pName );
+ if( pImplLib->mbSharedIndexFile || pImplLib->mbExtension )
+ {
+ nLibsToSave--;
+ }
+ }
+ // Write to storage?
+ bool bStorage = i_rStorage.is();
+ uno::Reference< embed::XStorage > xSourceLibrariesStor;
+ uno::Reference< embed::XStorage > xTargetLibrariesStor;
+ OUString sTempTargetStorName;
+ const bool bInplaceStorage = bStorage && ( i_rStorage == mxStorage );
+
+ if( nLibsToSave == 0 )
+ {
+ if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) )
+ {
+ mxStorage->removeElement(maLibrariesDir);
+ }
+ return;
+ }
+
+ if ( bStorage )
+ {
+ // Don't write if only empty standard lib exists
+ if ( ( nLibsToSave == 1 ) && ( aNames[0] == "Standard" ) )
+ {
+ Any aLibAny = maNameContainer->getByName( aNames[0] );
+ Reference< XNameAccess > xNameAccess;
+ aLibAny >>= xNameAccess;
+ if ( ! xNameAccess->hasElements() )
+ {
+ if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) )
+ {
+ mxStorage->removeElement(maLibrariesDir);
+ }
+ return;
+ }
+ }
+
+ // create the empty target storage
+ try
+ {
+ OUString sTargetLibrariesStoreName;
+ if ( bInplaceStorage )
+ {
+ // create a temporary target storage
+ const OUStringBuffer aTempTargetNameBase = maLibrariesDir + "_temp_";
+ sal_Int32 index = 0;
+ do
+ {
+ OUStringBuffer aTempTargetName( aTempTargetNameBase );
+ aTempTargetName.append( index++ );
+
+ sTargetLibrariesStoreName = aTempTargetName.makeStringAndClear();
+ if ( !i_rStorage->hasByName( sTargetLibrariesStoreName ) )
+ {
+ break;
+ }
+ }
+ while ( true );
+ sTempTargetStorName = sTargetLibrariesStoreName;
+ }
+ else
+ {
+ sTargetLibrariesStoreName = maLibrariesDir;
+ if ( i_rStorage->hasByName( sTargetLibrariesStoreName ) )
+ {
+ i_rStorage->removeElement( sTargetLibrariesStoreName );
+ }
+ }
+
+ xTargetLibrariesStor.set( i_rStorage->openStorageElement( sTargetLibrariesStoreName, embed::ElementModes::READWRITE ), UNO_SET_THROW );
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("basic");
+ return;
+ }
+
+ // open the source storage which might be used to copy yet-unmodified libraries
+ try
+ {
+ if ( mxStorage->hasByName( maLibrariesDir ) || bInplaceStorage )
+ {
+ xSourceLibrariesStor = mxStorage->openStorageElement( maLibrariesDir,
+ bInplaceStorage ? embed::ElementModes::READWRITE : embed::ElementModes::READ );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("basic");
+ return;
+ }
+ }
+
+ int iArray = 0;
+ pName = aNames.getConstArray();
+ ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs;
+ auto pLibArray = std::make_unique< ::xmlscript::LibDescriptorArray > ( nLibsToSave );
+ for( ; pName != pNamesEnd; ++pName )
+ {
+ SfxLibrary* pImplLib = getImplLib( *pName );
+ if( pImplLib->mbSharedIndexFile )
+ {
+ continue;
+ }
+ const bool bExtensionLib = pImplLib->mbExtension;
+ ::xmlscript::LibDescriptor& rLib = bExtensionLib ?
+ aLibDescriptorForExtensionLibs : pLibArray->mpLibs[iArray];
+ if( !bExtensionLib )
+ {
+ iArray++;
+ }
+ rLib.aName = *pName;
+
+ rLib.bLink = pImplLib->mbLink;
+ if( !bStorage || pImplLib->mbLink )
+ {
+ rLib.aStorageURL = ( pImplLib->maUnexpandedStorageURL.getLength() ) ?
+ pImplLib->maUnexpandedStorageURL : pImplLib->maLibInfoFileURL;
+ }
+ rLib.bReadOnly = pImplLib->mbReadOnly;
+ rLib.bPreload = pImplLib->mbPreload;
+ rLib.bPasswordProtected = pImplLib->mbPasswordProtected;
+ rLib.aElementNames = pImplLib->getElementNames();
+
+ if( pImplLib->implIsModified() || bComplete )
+ {
+// Testing pImplLib->implIsModified() is not reliable,
+// IMHO the value of pImplLib->implIsModified() should
+// reflect whether the library ( in-memory ) model
+// is in sync with the library container's own storage. Currently
+// whenever the library model is written to *any* storage
+// pImplLib->implSetModified( sal_False ) is called
+// The way the code works, especially the way that sfx uses
+// temp storage when saving ( and later sets the root storage of the
+// library container ) and similar madness in dbaccess means some surgery
+// is required to make it possible to successfully use this optimisation
+// It would be possible to do the implSetModified() call below only
+// conditionally, but that would require an additional boolean to be
+// passed in via the XStorageBasedDocument::storeLibrariesToStorage()...
+// fdo#68983: If there's a password and the password is not known, only
+// copying the storage works!
+ // Can we simply copy the storage?
+ bool isCopyStorage = !mbOldInfoFormat && !mbOasis2OOoFormat
+ && !pImplLib->isLoadedStorable()
+ && xSourceLibrariesStor.is() /* null for user profile */;
+ if (isCopyStorage)
+ {
+ try
+ {
+ (void)xSourceLibrariesStor->isStorageElement(rLib.aName);
+ }
+ catch (container::NoSuchElementException const&)
+ {
+ isCopyStorage = false;
+ }
+ }
+ if (isCopyStorage)
+ {
+ try
+ {
+ xSourceLibrariesStor->copyElementTo( rLib.aName, xTargetLibrariesStor, rLib.aName );
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("basic");
+ // TODO: error handling?
+ }
+ }
+ else
+ {
+ uno::Reference< embed::XStorage > xLibraryStor;
+ if( bStorage )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ try
+ {
+#endif
+ xLibraryStor = xTargetLibrariesStor->openStorageElement(
+ rLib.aName,
+ embed::ElementModes::READWRITE );
+#if OSL_DEBUG_LEVEL > 0
+ }
+ catch(const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION(
+ "basic",
+ "couldn't create sub storage for library \"" << rLib.aName << "\"");
+ throw;
+ }
+#endif
+ }
+
+ // Maybe lib is not loaded?!
+ if( bComplete )
+ {
+ loadLibrary( rLib.aName );
+ }
+ if( pImplLib->mbPasswordProtected )
+ {
+ implStorePasswordLibrary( pImplLib, rLib.aName, xLibraryStor, uno::Reference< task::XInteractionHandler >() );
+ // TODO: Check return value
+ }
+ else
+ {
+ implStoreLibrary( pImplLib, rLib.aName, xLibraryStor );
+ }
+ implStoreLibraryIndexFile( pImplLib, rLib, xLibraryStor );
+ if( bStorage )
+ {
+ try
+ {
+ uno::Reference< embed::XTransactedObject > xTransact( xLibraryStor, uno::UNO_QUERY_THROW );
+ xTransact->commit();
+ }
+ catch(const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("basic");
+ // TODO: error handling
+ throw;
+ }
+ }
+ }
+ maModifiable.setModified( true );
+ pImplLib->implSetModified( false );
+ }
+
+ // For container info ReadOnly refers to mbReadOnlyLink
+ rLib.bReadOnly = pImplLib->mbReadOnlyLink;
+ }
+
+ // if we did an in-place save into a storage (i.e. a save into the storage we were already based on),
+ // then we need to clean up the temporary storage we used for this
+ if ( bInplaceStorage && !sTempTargetStorName.isEmpty() )
+ {
+ SAL_WARN_IF(
+ !xSourceLibrariesStor.is(), "basic",
+ ("SfxLibrariesContainer::storeLibraries_impl: unexpected: we should"
+ " have a source storage here!"));
+ try
+ {
+ // for this, we first remove everything from the source storage, then copy the complete content
+ // from the temporary target storage. From then on, what used to be the "source storage" becomes
+ // the "target storage" for all subsequent operations.
+
+ // (We cannot simply remove the storage, denoted by maLibrariesDir, from i_rStorage - there might be
+ // open references to it.)
+
+ if ( xSourceLibrariesStor.is() )
+ {
+ // remove
+ const Sequence< OUString > aRemoveNames( xSourceLibrariesStor->getElementNames() );
+ for ( auto const & removeName : aRemoveNames )
+ {
+ xSourceLibrariesStor->removeElement( removeName );
+ }
+
+ // copy
+ const Sequence< OUString > aCopyNames( xTargetLibrariesStor->getElementNames() );
+ for ( auto const & copyName : aCopyNames )
+ {
+ xTargetLibrariesStor->copyElementTo( copyName, xSourceLibrariesStor, copyName );
+ }
+ }
+
+ // close and remove temp target
+ xTargetLibrariesStor->dispose();
+ i_rStorage->removeElement( sTempTargetStorName );
+ xTargetLibrariesStor.clear();
+ sTempTargetStorName.clear();
+
+ // adjust target
+ xTargetLibrariesStor = xSourceLibrariesStor;
+ xSourceLibrariesStor.clear();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("basic");
+ throw;
+ }
+ }
+
+ if( !mbOldInfoFormat && !maModifiable.isModified() )
+ {
+ return;
+ }
+ maModifiable.setModified( false );
+ mbOldInfoFormat = false;
+
+ // Write library container info
+ // Create sax writer
+ Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
+
+ // Write info file
+ uno::Reference< io::XOutputStream > xOut;
+ uno::Reference< io::XStream > xInfoStream;
+ if( bStorage )
+ {
+ OUString aStreamName = maInfoFileName + "-lc.xml";
+
+ try
+ {
+ xInfoStream = xTargetLibrariesStor->openStreamElement( aStreamName, embed::ElementModes::READWRITE );
+ uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY_THROW );
+ xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
+
+ // #87671 Allow encryption
+ xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
+
+ xOut = xInfoStream->getOutputStream();
+ }
+ catch(const uno::Exception& )
+ {
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+ }
+ else
+ {
+ // Create Output stream
+ INetURLObject aLibInfoInetObj( o3tl::getToken(maLibraryPath, 1, ';') );
+ aLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ aLibInfoInetObj.setExtension( u"xlc" );
+ OUString aLibInfoPath( aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ try
+ {
+ if( mxSFI->exists( aLibInfoPath ) )
+ {
+ mxSFI->kill( aLibInfoPath );
+ }
+ xOut = mxSFI->openFileWrite( aLibInfoPath );
+ }
+ catch(const Exception& )
+ {
+ xOut.clear();
+ SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath );
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+
+ }
+ if( !xOut.is() )
+ {
+ SAL_WARN("basic", "couldn't open output stream");
+ return;
+ }
+
+ xWriter->setOutputStream( xOut );
+
+ try
+ {
+ xmlscript::exportLibraryContainer( xWriter, pLibArray.get() );
+ if ( bStorage )
+ {
+ uno::Reference< embed::XTransactedObject > xTransact( xTargetLibrariesStor, uno::UNO_QUERY_THROW );
+ xTransact->commit();
+ }
+ }
+ catch(const uno::Exception& )
+ {
+ SAL_WARN("basic", "Problem during storing of libraries!");
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+}
+
+
+// Methods XElementAccess
+Type SAL_CALL SfxLibraryContainer::getElementType()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return maNameContainer->getElementType();
+}
+
+sal_Bool SfxLibraryContainer::hasElements()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ bool bRet = maNameContainer->hasElements();
+ return bRet;
+}
+
+// Methods XNameAccess
+Any SfxLibraryContainer::getByName( const OUString& aName )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ Any aRetAny = maNameContainer->getByName( aName ) ;
+ return aRetAny;
+}
+
+Sequence< OUString > SfxLibraryContainer::getElementNames()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return maNameContainer->getElementNames();
+}
+
+sal_Bool SfxLibraryContainer::hasByName( const OUString& aName )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return maNameContainer->hasByName( aName ) ;
+}
+
+// Methods XLibraryContainer
+Reference< XNameContainer > SAL_CALL SfxLibraryContainer::createLibrary( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ rtl::Reference<SfxLibrary> pNewLib = implCreateLibrary( Name );
+ pNewLib->maLibElementFileExtension = maLibElementFileExtension;
+
+ createVariableURL( pNewLib->maUnexpandedStorageURL, Name, maInfoFileName, true );
+
+ Reference< XNameAccess > xNameAccess( pNewLib );
+ Any aElement;
+ aElement <<= xNameAccess;
+ maNameContainer->insertByName( Name, aElement );
+ maModifiable.setModified( true );
+ Reference< XNameContainer > xRet( xNameAccess, UNO_QUERY );
+ return xRet;
+}
+
+Reference< XNameAccess > SAL_CALL SfxLibraryContainer::createLibraryLink
+ ( const OUString& Name, const OUString& StorageURL, sal_Bool ReadOnly )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ // TODO: Check other reasons to force ReadOnly status
+ //if( !ReadOnly )
+ //{
+ //}
+
+ OUString aLibInfoFileURL;
+ OUString aLibDirURL;
+ OUString aUnexpandedStorageURL;
+ checkStorageURL( StorageURL, aLibInfoFileURL, aLibDirURL, aUnexpandedStorageURL );
+
+
+ rtl::Reference<SfxLibrary> pNewLib = implCreateLibraryLink( Name, aLibInfoFileURL, aLibDirURL, ReadOnly );
+ pNewLib->maLibElementFileExtension = maLibElementFileExtension;
+ pNewLib->maUnexpandedStorageURL = aUnexpandedStorageURL;
+ pNewLib->maOriginalStorageURL = StorageURL;
+
+ uno::Reference< embed::XStorage > xDummyStor;
+ ::xmlscript::LibDescriptor aLibDesc;
+ implLoadLibraryIndexFile( pNewLib.get(), aLibDesc, xDummyStor, OUString() );
+ implImportLibDescriptor( pNewLib.get(), aLibDesc );
+
+ Reference< XNameAccess > xRet( pNewLib );
+ Any aElement;
+ aElement <<= xRet;
+ maNameContainer->insertByName( Name, aElement );
+ maModifiable.setModified( true );
+
+ if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 )
+ {
+ pNewLib->mbExtension = true;
+ }
+ else if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1
+ || StorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 )
+ {
+ pNewLib->mbExtension = true;
+ pNewLib->mbReadOnly = true;
+ }
+
+ return xRet;
+}
+
+void SAL_CALL SfxLibraryContainer::removeLibrary( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ // Get and hold library before removing
+ Any aLibAny = maNameContainer->getByName( Name ) ;
+ Reference< XNameAccess > xNameAccess;
+ aLibAny >>= xNameAccess;
+ SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
+ if( pImplLib->mbReadOnly && !pImplLib->mbLink )
+ {
+ throw IllegalArgumentException("readonly && !link", static_cast<cppu::OWeakObject*>(this), 1);
+ }
+ // Remove from container
+ maNameContainer->removeByName( Name );
+ maModifiable.setModified( true );
+
+ // Delete library files, but not for linked libraries
+ if( pImplLib->mbLink )
+ return;
+
+ if( mxStorage.is() )
+ {
+ return;
+ }
+ if( xNameAccess->hasElements() )
+ {
+ Sequence< OUString > aNames = pImplLib->getElementNames();
+ sal_Int32 nNameCount = aNames.getLength();
+ const OUString* pNames = aNames.getConstArray();
+ for( sal_Int32 i = 0 ; i < nNameCount ; ++i, ++pNames )
+ {
+ pImplLib->removeElementWithoutChecks( *pNames, SfxLibrary::LibraryContainerAccess() );
+ }
+ }
+
+ // Delete index file
+ createAppLibraryFolder( pImplLib, Name );
+ OUString aLibInfoPath = pImplLib->maLibInfoFileURL;
+ try
+ {
+ if( mxSFI->exists( aLibInfoPath ) )
+ {
+ mxSFI->kill( aLibInfoPath );
+ }
+ }
+ catch(const Exception& ) {}
+
+ // Delete folder if empty
+ INetURLObject aInetObj( o3tl::getToken(maLibraryPath, 1, ';') );
+ aInetObj.insertName( Name, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ try
+ {
+ if( mxSFI->isFolder( aLibDirPath ) )
+ {
+ Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true );
+ sal_Int32 nCount = aContentSeq.getLength();
+ if( !nCount )
+ {
+ mxSFI->kill( aLibDirPath );
+ }
+ }
+ }
+ catch(const Exception& )
+ {
+ }
+}
+
+sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLoaded( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+ bool bRet = pImplLib->mbLoaded;
+ return bRet;
+}
+
+
+void SAL_CALL SfxLibraryContainer::loadLibrary( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ Any aLibAny = maNameContainer->getByName( Name ) ;
+ Reference< XNameAccess > xNameAccess;
+ aLibAny >>= xNameAccess;
+ SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
+
+ bool bLoaded = pImplLib->mbLoaded;
+ pImplLib->mbLoaded = true;
+ if( bLoaded || !xNameAccess->hasElements() )
+ return;
+
+ if( pImplLib->mbPasswordProtected )
+ {
+ implLoadPasswordLibrary( pImplLib, Name );
+ return;
+ }
+
+ bool bLink = pImplLib->mbLink;
+ bool bStorage = mxStorage.is() && !bLink;
+
+ uno::Reference< embed::XStorage > xLibrariesStor;
+ uno::Reference< embed::XStorage > xLibraryStor;
+ if( bStorage )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ try
+ {
+#endif
+ xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
+ SAL_WARN_IF(
+ !xLibrariesStor.is(), "basic",
+ ("The method must either throw exception or return a"
+ " storage!"));
+ if ( !xLibrariesStor.is() )
+ {
+ throw uno::RuntimeException("null returned from openStorageElement",static_cast< cppu::OWeakObject * >(this));
+ }
+
+ xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
+ SAL_WARN_IF(
+ !xLibraryStor.is(), "basic",
+ ("The method must either throw exception or return a"
+ " storage!"));
+ if ( !xLibrariesStor.is() )
+ {
+ throw uno::RuntimeException("null returned from openStorageElement",static_cast< cppu::OWeakObject * >(this));
+ }
+#if OSL_DEBUG_LEVEL > 0
+ }
+ catch(const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION(
+ "basic",
+ "couldn't open sub storage for library \"" << Name << "\"");
+ throw;
+ }
+#endif
+ }
+
+ Sequence< OUString > aNames = pImplLib->getElementNames();
+ sal_Int32 nNameCount = aNames.getLength();
+ const OUString* pNames = aNames.getConstArray();
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aElementName = pNames[ i ];
+
+ OUString aFile;
+ uno::Reference< io::XInputStream > xInStream;
+
+ if( bStorage )
+ {
+ uno::Reference< io::XStream > xElementStream;
+
+ aFile = aElementName + ".xml";
+
+ try
+ {
+ xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ );
+ }
+ catch(const uno::Exception& )
+ {}
+
+ if( !xElementStream.is() )
+ {
+ // Check for EA2 document version with wrong extensions
+ aFile = aElementName + "." + maLibElementFileExtension;
+ try
+ {
+ xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ );
+ }
+ catch(const uno::Exception& )
+ {}
+ }
+
+ if ( xElementStream.is() )
+ {
+ xInStream = xElementStream->getInputStream();
+ }
+ if ( !xInStream.is() )
+ {
+ SAL_WARN(
+ "basic",
+ "couldn't open library element stream - attempted to"
+ " open library \"" << Name << '"');
+ throw RuntimeException("couldn't open library element stream", *this);
+ }
+ }
+ else
+ {
+ OUString aLibDirPath = pImplLib->maStorageURL;
+ INetURLObject aElementInetObj( aLibDirPath );
+ aElementInetObj.insertName( aElementName, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aElementInetObj.setExtension( maLibElementFileExtension );
+ aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ Reference< XNameContainer > xLib( pImplLib );
+ Any aAny = importLibraryElement( xLib, aElementName,
+ aFile, xInStream );
+ if( pImplLib->hasByName( aElementName ) )
+ {
+ if( aAny.hasValue() )
+ {
+ pImplLib->maNameContainer->replaceByName( aElementName, aAny );
+ }
+ }
+ else
+ {
+ pImplLib->maNameContainer->insertNoCheck(aElementName, aAny);
+ }
+ }
+ pImplLib->implSetModified( false );
+}
+
+// Methods XLibraryContainer2
+sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLink( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+ bool bRet = pImplLib->mbLink;
+ return bRet;
+}
+
+OUString SAL_CALL SfxLibraryContainer::getLibraryLinkURL( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+ bool bLink = pImplLib->mbLink;
+ if( !bLink )
+ {
+ throw IllegalArgumentException("!link", static_cast<cppu::OWeakObject*>(this), 1);
+ }
+ OUString aRetStr = pImplLib->maLibInfoFileURL;
+ return aRetStr;
+}
+
+sal_Bool SAL_CALL SfxLibraryContainer::isLibraryReadOnly( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+ bool bRet = pImplLib->mbReadOnly || (pImplLib->mbLink && pImplLib->mbReadOnlyLink);
+ return bRet;
+}
+
+void SAL_CALL SfxLibraryContainer::setLibraryReadOnly( const OUString& Name, sal_Bool bReadOnly )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+ if( pImplLib->mbLink )
+ {
+ if( pImplLib->mbReadOnlyLink != bool(bReadOnly) )
+ {
+ pImplLib->mbReadOnlyLink = bReadOnly;
+ pImplLib->implSetModified( true );
+ maModifiable.setModified( true );
+ }
+ }
+ else
+ {
+ if( pImplLib->mbReadOnly != bool(bReadOnly) )
+ {
+ pImplLib->mbReadOnly = bReadOnly;
+ pImplLib->implSetModified( true );
+ }
+ }
+}
+
+void SAL_CALL SfxLibraryContainer::renameLibrary( const OUString& Name, const OUString& NewName )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ if( maNameContainer->hasByName( NewName ) )
+ {
+ throw ElementExistException();
+ }
+ // Get and hold library before removing
+ Any aLibAny = maNameContainer->getByName( Name ) ;
+
+ // #i24094 Maybe lib is not loaded!
+ Reference< XNameAccess > xNameAccess;
+ aLibAny >>= xNameAccess;
+ SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
+ if( pImplLib->mbPasswordProtected && !pImplLib->mbPasswordVerified )
+ {
+ return; // Lib with unverified password cannot be renamed
+ }
+ loadLibrary( Name );
+
+ // Remove from container
+ maNameContainer->removeByName( Name );
+ maModifiable.setModified( true );
+
+ // Rename library folder, but not for linked libraries
+ bool bMovedSuccessful = true;
+
+ // Rename files
+ bool bStorage = mxStorage.is();
+ if( !bStorage && !pImplLib->mbLink )
+ {
+ bMovedSuccessful = false;
+
+ OUString aLibDirPath = pImplLib->maStorageURL;
+
+ INetURLObject aDestInetObj( o3tl::getToken(maLibraryPath, 1, ';'));
+ aDestInetObj.insertName( NewName, true, INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ OUString aDestDirPath = aDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ // Store new URL
+ OUString aLibInfoFileURL = pImplLib->maLibInfoFileURL;
+ checkStorageURL( aDestDirPath, pImplLib->maLibInfoFileURL, pImplLib->maStorageURL,
+ pImplLib->maUnexpandedStorageURL );
+
+ try
+ {
+ if( mxSFI->isFolder( aLibDirPath ) )
+ {
+ if( !mxSFI->isFolder( aDestDirPath ) )
+ {
+ mxSFI->createFolder( aDestDirPath );
+ }
+ // Move index file
+ try
+ {
+ if( mxSFI->exists( pImplLib->maLibInfoFileURL ) )
+ {
+ mxSFI->kill( pImplLib->maLibInfoFileURL );
+ }
+ mxSFI->move( aLibInfoFileURL, pImplLib->maLibInfoFileURL );
+ }
+ catch(const Exception& )
+ {
+ }
+
+ Sequence< OUString > aElementNames = xNameAccess->getElementNames();
+ sal_Int32 nNameCount = aElementNames.getLength();
+ const OUString* pNames = aElementNames.getConstArray();
+ for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
+ {
+ OUString aElementName = pNames[ i ];
+
+ INetURLObject aElementInetObj( aLibDirPath );
+ aElementInetObj.insertName( aElementName, false,
+ INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
+ aElementInetObj.setExtension( maLibElementFileExtension );
+ OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ INetURLObject aElementDestInetObj( aDestDirPath );
+ aElementDestInetObj.insertName( aElementName, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aElementDestInetObj.setExtension( maLibElementFileExtension );
+ OUString aDestElementPath( aElementDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+
+ try
+ {
+ if( mxSFI->exists( aDestElementPath ) )
+ {
+ mxSFI->kill( aDestElementPath );
+ }
+ mxSFI->move( aElementPath, aDestElementPath );
+ }
+ catch(const Exception& )
+ {
+ }
+ }
+ pImplLib->storeResourcesAsURL( aDestDirPath, NewName );
+
+ // Delete folder if empty
+ Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true );
+ sal_Int32 nCount = aContentSeq.getLength();
+ if( !nCount )
+ {
+ mxSFI->kill( aLibDirPath );
+ }
+
+ bMovedSuccessful = true;
+ pImplLib->implSetModified( true );
+ }
+ }
+ catch(const Exception& )
+ {
+ // Restore old library
+ maNameContainer->insertByName( Name, aLibAny ) ;
+ }
+ }
+
+ if( bStorage && !pImplLib->mbLink )
+ {
+ pImplLib->implSetModified( true );
+ }
+ if( bMovedSuccessful )
+ {
+ maNameContainer->insertByName( NewName, aLibAny ) ;
+ }
+}
+
+
+// Methods XInitialization
+void SAL_CALL SfxLibraryContainer::initialize( const Sequence< Any >& _rArguments )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ sal_Int32 nArgCount = _rArguments.getLength();
+ if ( nArgCount != 1 )
+ throw IllegalArgumentException("too many args", static_cast<cppu::OWeakObject*>(this), -1);
+
+ OUString sInitialDocumentURL;
+ Reference< XStorageBasedDocument > xDocument;
+ if ( _rArguments[0] >>= sInitialDocumentURL )
+ {
+ init( sInitialDocumentURL, nullptr );
+ return;
+ }
+
+ if ( _rArguments[0] >>= xDocument )
+ {
+ initializeFromDocument( xDocument );
+ return;
+ }
+ throw IllegalArgumentException("arg1 unknown type", static_cast<cppu::OWeakObject*>(this), 1);
+
+}
+
+void SfxLibraryContainer::initializeFromDocument( const Reference< XStorageBasedDocument >& _rxDocument )
+{
+ // check whether this is a valid OfficeDocument, and obtain the document's root storage
+ Reference< XStorage > xDocStorage;
+ try
+ {
+ Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY_THROW );
+ if ( xSI->supportsService("com.sun.star.document.OfficeDocument"))
+ {
+ xDocStorage.set( _rxDocument->getDocumentStorage(), UNO_SET_THROW );
+ }
+ Reference< XModel > xDocument( _rxDocument, UNO_QUERY_THROW );
+ Reference< XComponent > xDocComponent( _rxDocument, UNO_QUERY_THROW );
+
+ mxOwnerDocument = xDocument;
+ startComponentListening( xDocComponent );
+ }
+ catch( const Exception& ) { }
+
+ if ( !xDocStorage.is() )
+ {
+ throw IllegalArgumentException("no doc storage", static_cast<cppu::OWeakObject*>(this), 1);
+ }
+ init( OUString(), xDocStorage );
+}
+
+// OEventListenerAdapter
+void SfxLibraryContainer::_disposing( const EventObject& _rSource )
+{
+#if OSL_DEBUG_LEVEL > 0
+ Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY );
+ SAL_WARN_IF(
+ xDocument != _rSource.Source || !xDocument.is(), "basic",
+ "SfxLibraryContainer::_disposing: where does this come from?");
+#else
+ (void)_rSource;
+#endif
+ dispose();
+}
+
+// OComponentHelper
+void SAL_CALL SfxLibraryContainer::disposing()
+{
+ Reference< XModel > xModel = mxOwnerDocument;
+ EventObject aEvent( xModel );
+ maVBAScriptListeners.disposeAndClear( aEvent );
+ stopAllComponentListening();
+ mxOwnerDocument.clear();
+}
+
+// Methods XLibraryContainerPassword
+sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordProtected( const OUString& )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordVerified( const OUString& )
+{
+ throw IllegalArgumentException();
+}
+
+sal_Bool SAL_CALL SfxLibraryContainer::verifyLibraryPassword( const OUString&, const OUString& )
+{
+ throw IllegalArgumentException();
+}
+
+void SAL_CALL SfxLibraryContainer::changeLibraryPassword(const OUString&, const OUString&, const OUString& )
+{
+ throw IllegalArgumentException();
+}
+
+// Methods XContainer
+void SAL_CALL SfxLibraryContainer::addContainerListener( const Reference< XContainerListener >& xListener )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
+ maNameContainer->addContainerListener( xListener );
+}
+
+void SAL_CALL SfxLibraryContainer::removeContainerListener( const Reference< XContainerListener >& xListener )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ maNameContainer->removeContainerListener( xListener );
+}
+
+// Methods XLibraryContainerExport
+void SAL_CALL SfxLibraryContainer::exportLibrary( const OUString& Name, const OUString& URL,
+ const Reference< XInteractionHandler >& Handler )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+
+ Reference< XSimpleFileAccess3 > xToUseSFI;
+ if( Handler.is() )
+ {
+ xToUseSFI = ucb::SimpleFileAccess::create( mxContext );
+ xToUseSFI->setInteractionHandler( Handler );
+ }
+
+ // Maybe lib is not loaded?!
+ loadLibrary( Name );
+
+ uno::Reference< css::embed::XStorage > xDummyStor;
+ if( pImplLib->mbPasswordProtected )
+ {
+ implStorePasswordLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler );
+ }
+ else
+ {
+ implStoreLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler );
+ }
+ ::xmlscript::LibDescriptor aLibDesc;
+ aLibDesc.aName = Name;
+ aLibDesc.bLink = false; // Link status gets lost?
+ aLibDesc.bReadOnly = pImplLib->mbReadOnly;
+ aLibDesc.bPreload = false; // Preload status gets lost?
+ aLibDesc.bPasswordProtected = pImplLib->mbPasswordProtected;
+ aLibDesc.aElementNames = pImplLib->getElementNames();
+
+ implStoreLibraryIndexFile( pImplLib, aLibDesc, xDummyStor, URL, xToUseSFI );
+}
+
+OUString SfxLibraryContainer::expand_url( const OUString& url )
+{
+ if (url.startsWithIgnoreAsciiCase( "vnd.sun.star.expand:" ))
+ {
+ return comphelper::getExpandedUri(mxContext, url);
+ }
+ else if( mxStringSubstitution.is() )
+ {
+ OUString ret( mxStringSubstitution->substituteVariables( url, false ) );
+ return ret;
+ }
+ else
+ {
+ return url;
+ }
+}
+
+//XLibraryContainer3
+OUString SAL_CALL SfxLibraryContainer::getOriginalLibraryLinkURL( const OUString& Name )
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ SfxLibrary* pImplLib = getImplLib( Name );
+ bool bLink = pImplLib->mbLink;
+ if( !bLink )
+ {
+ throw IllegalArgumentException("!link", static_cast<cppu::OWeakObject*>(this), 1);
+ }
+ OUString aRetStr = pImplLib->maOriginalStorageURL;
+ return aRetStr;
+}
+
+
+// XVBACompatibility
+sal_Bool SAL_CALL SfxLibraryContainer::getVBACompatibilityMode()
+{
+ return mbVBACompat;
+}
+
+void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( sal_Bool _vbacompatmodeon )
+{
+ /* The member variable mbVBACompat must be set first, the following call
+ to getBasicManager() may call getVBACompatibilityMode() which returns
+ this value. */
+ mbVBACompat = _vbacompatmodeon;
+ BasicManager* pBasMgr = getBasicManager();
+ if( !pBasMgr )
+ return;
+
+ // get the standard library
+ OUString aLibName = pBasMgr->GetName();
+ if ( aLibName.isEmpty())
+ {
+ aLibName = "Standard";
+ }
+ if( StarBASIC* pBasic = pBasMgr->GetLib( aLibName ) )
+ {
+ pBasic->SetVBAEnabled( _vbacompatmodeon );
+ }
+ /* If in VBA compatibility mode, force creation of the VBA Globals
+ object. Each application will create an instance of its own
+ implementation and store it in its Basic manager. Implementations
+ will do all necessary additional initialization, such as
+ registering the global "This***Doc" UNO constant, starting the
+ document events processor etc.
+ */
+ if( mbVBACompat ) try
+ {
+ Reference< XModel > xModel( mxOwnerDocument ); // weak-ref -> ref
+ Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
+ xFactory->createInstance("ooo.vba.VBAGlobals");
+ }
+ catch(const Exception& )
+ {
+ }
+}
+
+void SAL_CALL SfxLibraryContainer::setProjectName( const OUString& _projectname )
+{
+ msProjectName = _projectname;
+ BasicManager* pBasMgr = getBasicManager();
+ // Temporary HACK
+ // Some parts of the VBA handling ( e.g. in core basic )
+ // code expect the name of the VBA project to be set as the name of
+ // the basic manager. Provide fail back here.
+ if( pBasMgr )
+ {
+ pBasMgr->SetName( msProjectName );
+ }
+}
+
+sal_Int32 SAL_CALL SfxLibraryContainer::getRunningVBAScripts()
+{
+ LibraryContainerMethodGuard aGuard( *this );
+ return mnRunningVBAScripts;
+}
+
+void SAL_CALL SfxLibraryContainer::addVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener )
+{
+ maVBAScriptListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SfxLibraryContainer::removeVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener )
+{
+ maVBAScriptListeners.removeInterface( rxListener );
+}
+
+void SAL_CALL SfxLibraryContainer::broadcastVBAScriptEvent( sal_Int32 nIdentifier, const OUString& rModuleName )
+{
+ // own lock for accessing the number of running scripts
+ enterMethod();
+ switch( nIdentifier )
+ {
+ case vba::VBAScriptEventId::SCRIPT_STARTED:
+ ++mnRunningVBAScripts;
+ break;
+ case vba::VBAScriptEventId::SCRIPT_STOPPED:
+ --mnRunningVBAScripts;
+ break;
+ }
+ leaveMethod();
+
+ Reference< XModel > xModel = mxOwnerDocument; // weak-ref -> ref
+ vba::VBAScriptEvent aEvent( Reference<XInterface>(xModel, UNO_QUERY), nIdentifier, rModuleName );
+ maVBAScriptListeners.notifyEach( &css::script::vba::XVBAScriptListener::notifyVBAScriptEvent, aEvent );
+}
+
+// Methods XPropertySet
+css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL SfxLibraryContainer::getPropertySetInfo()
+{
+ return uno::Reference<beans::XPropertySetInfo>();
+}
+
+void SAL_CALL SfxLibraryContainer::setPropertyValue(const OUString& aPropertyName,
+ const uno::Any& aValue)
+{
+ if (aPropertyName != sVBATextEncodingPropName)
+ throw UnknownPropertyException(aPropertyName, static_cast<uno::XWeak*>(this));
+ aValue >>= meVBATextEncoding;
+}
+
+css::uno::Any SAL_CALL SfxLibraryContainer::getPropertyValue(const OUString& aPropertyName)
+{
+ if (aPropertyName == sVBATextEncodingPropName)
+ return uno::Any(meVBATextEncoding);
+ throw UnknownPropertyException(aPropertyName, static_cast<uno::XWeak*>(this));
+}
+
+void SAL_CALL SfxLibraryContainer::addPropertyChangeListener(
+ const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener>& /* xListener */)
+{
+ throw NoSupportException();
+}
+
+void SAL_CALL SfxLibraryContainer::removePropertyChangeListener(
+ const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener>& /* aListener */)
+{
+ throw NoSupportException();
+}
+
+void SAL_CALL SfxLibraryContainer::addVetoableChangeListener(
+ const OUString& /* PropertyName */, const Reference<XVetoableChangeListener>& /* aListener */)
+{
+ throw NoSupportException();
+}
+
+void SAL_CALL SfxLibraryContainer::removeVetoableChangeListener(
+ const OUString& /* PropertyName */, const Reference<XVetoableChangeListener>& /* aListener */)
+{
+ throw NoSupportException();
+}
+
+// Methods XServiceInfo
+sal_Bool SAL_CALL SfxLibraryContainer::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+// Implementation class SfxLibrary
+
+// Ctor
+SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType,
+ const Reference< XSimpleFileAccess3 >& xSFI )
+ : OComponentHelper( m_aMutex )
+ , mxSFI( xSFI )
+ , mrModifiable( _rModifiable )
+ , maNameContainer( new NameContainer(aType) )
+ , mbLoaded( true )
+ , mbIsModified( true )
+ , mbInitialised( false )
+ , mbLink( false )
+ , mbReadOnly( false )
+ , mbReadOnlyLink( false )
+ , mbPreload( false )
+ , mbPasswordProtected( false )
+ , mbPasswordVerified( false )
+ , mbDoc50Password( false )
+ , mbSharedIndexFile( false )
+ , mbExtension( false )
+{
+}
+
+SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType,
+ const Reference< XSimpleFileAccess3 >& xSFI,
+ OUString aLibInfoFileURL, OUString aStorageURL, bool ReadOnly )
+ : OComponentHelper( m_aMutex )
+ , mxSFI( xSFI )
+ , mrModifiable( _rModifiable )
+ , maNameContainer( new NameContainer(aType) )
+ , mbLoaded( false )
+ , mbIsModified( true )
+ , mbInitialised( false )
+ , maLibInfoFileURL(std::move( aLibInfoFileURL ))
+ , maStorageURL(std::move( aStorageURL ))
+ , mbLink( true )
+ , mbReadOnly( false )
+ , mbReadOnlyLink( ReadOnly )
+ , mbPreload( false )
+ , mbPasswordProtected( false )
+ , mbPasswordVerified( false )
+ , mbDoc50Password( false )
+ , mbSharedIndexFile( false )
+ , mbExtension( false )
+{
+}
+
+bool SfxLibrary::isLoadedStorable()
+{
+ return mbLoaded && (!mbPasswordProtected || mbPasswordVerified);
+}
+
+void SfxLibrary::implSetModified( bool _bIsModified )
+{
+ if ( mbIsModified == _bIsModified )
+ {
+ return;
+ }
+ mbIsModified = _bIsModified;
+ if ( mbIsModified )
+ {
+ mrModifiable.setModified( true );
+ }
+}
+
+// Methods XInterface
+Any SAL_CALL SfxLibrary::queryInterface( const Type& rType )
+{
+ Any aRet =
+ ::cppu::queryInterface(
+ rType,
+ static_cast< XContainer * >( this ),
+ static_cast< XNameContainer * >( this ),
+ static_cast< XNameAccess * >( this ),
+ static_cast< XElementAccess * >( this ),
+ static_cast< XChangesNotifier * >( this ) );
+ if( !aRet.hasValue() )
+ {
+ aRet = OComponentHelper::queryInterface( rType );
+ }
+ return aRet;
+}
+
+// Methods XElementAccess
+Type SfxLibrary::getElementType()
+{
+ return maNameContainer->getElementType();
+}
+
+sal_Bool SfxLibrary::hasElements()
+{
+ bool bRet = maNameContainer->hasElements();
+ return bRet;
+}
+
+// Methods XNameAccess
+Any SfxLibrary::getByName( const OUString& aName )
+{
+ impl_checkLoaded();
+
+ Any aRetAny = maNameContainer->getByName( aName ) ;
+ return aRetAny;
+}
+
+Sequence< OUString > SfxLibrary::getElementNames()
+{
+ return maNameContainer->getElementNames();
+}
+
+sal_Bool SfxLibrary::hasByName( const OUString& aName )
+{
+ bool bRet = maNameContainer->hasByName( aName );
+ return bRet;
+}
+
+void SfxLibrary::impl_checkReadOnly()
+{
+ if( mbReadOnly || (mbLink && mbReadOnlyLink) )
+ {
+ throw IllegalArgumentException(
+ "Library is readonly.",
+ // TODO: resource
+ *this, 0
+ );
+ }
+}
+
+void SfxLibrary::impl_checkLoaded()
+{
+ if ( !mbLoaded )
+ {
+ throw WrappedTargetException(
+ OUString(),
+ *this,
+ Any( LibraryNotLoadedException(
+ OUString(),
+ *this
+ ) )
+ );
+ }
+}
+
+// Methods XNameReplace
+void SfxLibrary::replaceByName( const OUString& aName, const Any& aElement )
+{
+ impl_checkReadOnly();
+ impl_checkLoaded();
+
+ SAL_WARN_IF(
+ !isLibraryElementValid(aElement), "basic",
+ "SfxLibrary::replaceByName: replacing element is invalid!");
+
+ maNameContainer->replaceByName( aName, aElement );
+ implSetModified( true );
+}
+
+
+// Methods XNameContainer
+void SfxLibrary::insertByName( const OUString& aName, const Any& aElement )
+{
+ impl_checkReadOnly();
+ impl_checkLoaded();
+
+ SAL_WARN_IF(
+ !isLibraryElementValid(aElement), "basic",
+ "SfxLibrary::insertByName: to-be-inserted element is invalid!");
+
+ maNameContainer->insertByName( aName, aElement );
+ implSetModified( true );
+}
+
+void SfxLibrary::impl_removeWithoutChecks( const OUString& _rElementName )
+{
+ maNameContainer->removeByName( _rElementName );
+ implSetModified( true );
+
+ // Remove element file
+ if( maStorageURL.isEmpty() )
+ return;
+
+ INetURLObject aElementInetObj( maStorageURL );
+ aElementInetObj.insertName( _rElementName, false,
+ INetURLObject::LAST_SEGMENT,
+ INetURLObject::EncodeMechanism::All );
+ aElementInetObj.setExtension( maLibElementFileExtension );
+ OUString aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ try
+ {
+ if( mxSFI->exists( aFile ) )
+ {
+ mxSFI->kill( aFile );
+ }
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("basic");
+ }
+}
+
+void SfxLibrary::removeByName( const OUString& Name )
+{
+ impl_checkReadOnly();
+ impl_checkLoaded();
+ impl_removeWithoutChecks( Name );
+}
+
+// XTypeProvider
+Sequence< Type > SfxLibrary::getTypes()
+{
+ static OTypeCollection ourTypes_NameContainer(
+ cppu::UnoType<XNameContainer>::get(),
+ cppu::UnoType<XContainer>::get(),
+ cppu::UnoType<XChangesNotifier>::get(),
+ OComponentHelper::getTypes() );
+
+ return ourTypes_NameContainer.getTypes();
+}
+
+
+Sequence< sal_Int8 > SfxLibrary::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// Methods XContainer
+void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener )
+{
+ maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
+ maNameContainer->addContainerListener( xListener );
+}
+
+void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerListener >& xListener )
+{
+ maNameContainer->removeContainerListener( xListener );
+}
+
+// Methods XChangesNotifier
+void SAL_CALL SfxLibrary::addChangesListener( const Reference< XChangesListener >& xListener )
+{
+ maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
+ maNameContainer->addChangesListener( xListener );
+}
+
+void SAL_CALL SfxLibrary::removeChangesListener( const Reference< XChangesListener >& xListener )
+{
+ maNameContainer->removeChangesListener( xListener );
+}
+
+
+// Implementation class ScriptExtensionIterator
+
+constexpr OUStringLiteral sBasicLibMediaType = u"application/vnd.sun.star.basic-library";
+constexpr OUStringLiteral sDialogLibMediaType = u"application/vnd.sun.star.dialog-library";
+
+ScriptExtensionIterator::ScriptExtensionIterator()
+ : m_xContext( comphelper::getProcessComponentContext() )
+ , m_eState( USER_EXTENSIONS )
+ , m_bUserPackagesLoaded( false )
+ , m_bSharedPackagesLoaded( false )
+ , m_bBundledPackagesLoaded( false )
+ , m_iUserPackage( 0 )
+ , m_iSharedPackage( 0 )
+ , m_iBundledPackage( 0 )
+ , m_pScriptSubPackageIterator( nullptr )
+{}
+
+OUString ScriptExtensionIterator::nextBasicOrDialogLibrary( bool& rbPureDialogLib )
+{
+ OUString aRetLib;
+
+ while( aRetLib.isEmpty() && m_eState != END_REACHED )
+ {
+ switch( m_eState )
+ {
+ case USER_EXTENSIONS:
+ {
+ Reference< deployment::XPackage > xScriptPackage =
+ implGetNextUserScriptPackage( rbPureDialogLib );
+ if( !xScriptPackage.is() )
+ {
+ break;
+ }
+ aRetLib = xScriptPackage->getURL();
+ break;
+ }
+
+ case SHARED_EXTENSIONS:
+ {
+ Reference< deployment::XPackage > xScriptPackage =
+ implGetNextSharedScriptPackage( rbPureDialogLib );
+ if( !xScriptPackage.is() )
+ {
+ break;
+ }
+ aRetLib = xScriptPackage->getURL();
+ break;
+ }
+ case BUNDLED_EXTENSIONS:
+ {
+ Reference< deployment::XPackage > xScriptPackage =
+ implGetNextBundledScriptPackage( rbPureDialogLib );
+ if( !xScriptPackage.is() )
+ {
+ break;
+ }
+ aRetLib = xScriptPackage->getURL();
+ break;
+ }
+ case END_REACHED:
+ SAL_WARN(
+ "basic",
+ ("ScriptExtensionIterator::nextBasicOrDialogLibrary():"
+ " Invalid case END_REACHED"));
+ break;
+ }
+ }
+
+ return aRetLib;
+}
+
+ScriptSubPackageIterator::ScriptSubPackageIterator( Reference< deployment::XPackage > const & xMainPackage )
+ : m_xMainPackage( xMainPackage )
+ , m_bIsValid( false )
+ , m_bIsBundle( false )
+ , m_nSubPkgCount( 0 )
+ , m_iNextSubPkg( 0 )
+{
+ if( !m_xMainPackage.is() )
+ {
+ return;
+ }
+ // Check if parent package is registered
+ beans::Optional< beans::Ambiguous<sal_Bool> > option( m_xMainPackage->isRegistered
+ ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
+ bool bRegistered = false;
+ if( option.IsPresent )
+ {
+ beans::Ambiguous<sal_Bool> const & reg = option.Value;
+ if( !reg.IsAmbiguous && reg.Value )
+ {
+ bRegistered = true;
+ }
+ }
+ if( bRegistered )
+ {
+ m_bIsValid = true;
+ if( m_xMainPackage->isBundle() )
+ {
+ m_bIsBundle = true;
+ m_aSubPkgSeq = m_xMainPackage->getBundle( Reference<task::XAbortChannel>(),
+ Reference<ucb::XCommandEnvironment>() );
+ m_nSubPkgCount = m_aSubPkgSeq.getLength();
+ }
+ }
+}
+
+Reference< deployment::XPackage > ScriptSubPackageIterator::getNextScriptSubPackage( bool& rbPureDialogLib )
+{
+ rbPureDialogLib = false;
+
+ Reference< deployment::XPackage > xScriptPackage;
+ if( !m_bIsValid )
+ {
+ return xScriptPackage;
+ }
+ if( m_bIsBundle )
+ {
+ const Reference< deployment::XPackage >* pSeq = m_aSubPkgSeq.getConstArray();
+ sal_Int32 iPkg;
+ for( iPkg = m_iNextSubPkg ; iPkg < m_nSubPkgCount ; ++iPkg )
+ {
+ const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
+ xScriptPackage = implDetectScriptPackage( xSubPkg, rbPureDialogLib );
+ if( xScriptPackage.is() )
+ {
+ break;
+ }
+ }
+ m_iNextSubPkg = iPkg + 1;
+ }
+ else
+ {
+ xScriptPackage = implDetectScriptPackage( m_xMainPackage, rbPureDialogLib );
+ m_bIsValid = false; // No more script packages
+ }
+
+ return xScriptPackage;
+}
+
+Reference< deployment::XPackage > ScriptSubPackageIterator::implDetectScriptPackage ( const Reference< deployment::XPackage >& rPackage,
+ bool& rbPureDialogLib )
+{
+ Reference< deployment::XPackage > xScriptPackage;
+
+ if( rPackage.is() )
+ {
+ const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = rPackage->getPackageType();
+ OUString aMediaType = xPackageTypeInfo->getMediaType();
+ if ( aMediaType == sBasicLibMediaType )
+ {
+ xScriptPackage = rPackage;
+ }
+ else if ( aMediaType == sDialogLibMediaType )
+ {
+ rbPureDialogLib = true;
+ xScriptPackage = rPackage;
+ }
+ }
+
+ return xScriptPackage;
+}
+
+Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextUserScriptPackage( bool& rbPureDialogLib )
+{
+ Reference< deployment::XPackage > xScriptPackage;
+
+ if( !m_bUserPackagesLoaded )
+ {
+ try
+ {
+ Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext );
+ m_aUserPackagesSeq = xManager->getDeployedExtensions("user",
+ Reference< task::XAbortChannel >(),
+ Reference< ucb::XCommandEnvironment >() );
+ }
+ catch(const css::uno::DeploymentException& )
+ {
+ // Special Office installations may not contain deployment code
+ m_eState = END_REACHED;
+ return xScriptPackage;
+ }
+
+ m_bUserPackagesLoaded = true;
+ }
+
+ if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
+ {
+ m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE
+ }
+ else
+ {
+ if( m_pScriptSubPackageIterator == nullptr )
+ {
+ const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
+ Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage ];
+ SAL_WARN_IF(
+ !xPackage.is(), "basic",
+ ("ScriptExtensionIterator::implGetNextUserScriptPackage():"
+ " Invalid package"));
+ m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
+ }
+
+ xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
+ if( !xScriptPackage.is() )
+ {
+ delete m_pScriptSubPackageIterator;
+ m_pScriptSubPackageIterator = nullptr;
+ m_iUserPackage++;
+ }
+ }
+
+ return xScriptPackage;
+}
+
+Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextSharedScriptPackage( bool& rbPureDialogLib )
+{
+ Reference< deployment::XPackage > xScriptPackage;
+
+ if( !m_bSharedPackagesLoaded )
+ {
+ try
+ {
+ Reference< XExtensionManager > xSharedManager = ExtensionManager::get( m_xContext );
+ m_aSharedPackagesSeq = xSharedManager->getDeployedExtensions("shared",
+ Reference< task::XAbortChannel >(),
+ Reference< ucb::XCommandEnvironment >() );
+ }
+ catch(const css::uno::DeploymentException& )
+ {
+ // Special Office installations may not contain deployment code
+ return xScriptPackage;
+ }
+
+ m_bSharedPackagesLoaded = true;
+ }
+
+ if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
+ {
+ m_eState = BUNDLED_EXTENSIONS;
+ }
+ else
+ {
+ if( m_pScriptSubPackageIterator == nullptr )
+ {
+ const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
+ Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage ];
+ SAL_WARN_IF(
+ !xPackage.is(), "basic",
+ ("ScriptExtensionIterator::implGetNextSharedScriptPackage():"
+ " Invalid package"));
+ m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
+ }
+
+ xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
+ if( !xScriptPackage.is() )
+ {
+ delete m_pScriptSubPackageIterator;
+ m_pScriptSubPackageIterator = nullptr;
+ m_iSharedPackage++;
+ }
+ }
+
+ return xScriptPackage;
+}
+
+Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextBundledScriptPackage( bool& rbPureDialogLib )
+{
+ Reference< deployment::XPackage > xScriptPackage;
+
+ if( !m_bBundledPackagesLoaded )
+ {
+ try
+ {
+ Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext );
+ m_aBundledPackagesSeq = xManager->getDeployedExtensions("bundled",
+ Reference< task::XAbortChannel >(),
+ Reference< ucb::XCommandEnvironment >() );
+ }
+ catch(const css::uno::DeploymentException& )
+ {
+ // Special Office installations may not contain deployment code
+ return xScriptPackage;
+ }
+
+ m_bBundledPackagesLoaded = true;
+ }
+
+ if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
+ {
+ m_eState = END_REACHED;
+ }
+ else
+ {
+ if( m_pScriptSubPackageIterator == nullptr )
+ {
+ const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray();
+ Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage ];
+ SAL_WARN_IF(
+ !xPackage.is(), "basic",
+ ("ScriptExtensionIterator::implGetNextBundledScriptPackage():"
+ " Invalid package"));
+ m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
+ }
+
+ xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
+ if( !xScriptPackage.is() )
+ {
+ delete m_pScriptSubPackageIterator;
+ m_pScriptSubPackageIterator = nullptr;
+ m_iBundledPackage++;
+ }
+ }
+
+ return xScriptPackage;
+}
+
+} // namespace basic
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */