Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/basic/source/uno/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 116 kB image not shown  

Quelle  namecont.cxx   Sprache: C

 
/* -*- 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 <o3tl/temporary.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 <comphelper/diagnose_ex.hxx>
#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 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()
{
    return !maMap.empty();
}

// Methods XNameAccess
Any NameContainer::getByName( const OUString& aName )
{
    auto aIt = maMap.find(aName);
    if (aIt == maMap.end())
    {
        throw NoSuchElementException(aName);
    }
    return aIt->second;
}

Sequence< OUString > NameContainer::getElementNames()
{
    return comphelper::mapKeysToSequence(maMap);
}

sal_Bool NameContainer::hasByName( const OUString& aName )
{
    return maMap.contains(aName);
}


// Methods XNameReplace
void NameContainer::replaceByName(const OUString& aName, const Any& aElement,
                                  std::unique_lock<std::mutex>& guard)
{
    const Type& aAnyType = aElement.getValueType();
    if( mType != aAnyType )
    {
        throw IllegalArgumentException(u"types do not match"_ustr, rOwner, 2);
    }
    auto aIt = maMap.find(aName);
    if (aIt == maMap.end())
    {
        throw NoSuchElementException(aName);
    }
    Any aOldElement = aIt->second;
    aIt->second = aElement;

    // Fire event
    if (maContainerListeners.getLength(guard) > 0)
    {
        ContainerEvent aEvent;
        aEvent.Source = mpxEventSource;
        aEvent.Accessor <<= aName;
        aEvent.Element = aElement;
        aEvent.ReplacedElement = aOldElement;
        maContainerListeners.notifyEach(guard, &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(guard) > 0)
    {
        ChangesEvent aEvent;
        aEvent.Source = mpxEventSource;
        aEvent.Base <<= aEvent.Source;
        aEvent.Changes = { { Any(aName), aElement, aOldElement } };
        maChangesListeners.notifyEach(guard, &XChangesListener::changesOccurred, aEvent);
    }
}

void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement,
                                  std::unique_lock<std::mutex>& guard)
{
    const Type& aAnyType = aElement.getValueType();
    if( mType != aAnyType )
    {
        throw IllegalArgumentException(u"types do not match"_ustr, rOwner, 2);
    }

    maMap[aName] = aElement;

    // Fire event
    if (maContainerListeners.getLength(guard) > 0)
    {
        ContainerEvent aEvent;
        aEvent.Source = mpxEventSource;
        aEvent.Accessor <<= aName;
        aEvent.Element = aElement;
        maContainerListeners.notifyEach(guard, &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(guard) > 0)
    {
        ChangesEvent aEvent;
        aEvent.Source = mpxEventSource;
        aEvent.Base <<= aEvent.Source;
        aEvent.Changes = { { Any(aName), aElement, {} } };
        maChangesListeners.notifyEach(guard, &XChangesListener::changesOccurred, aEvent);
    }
}

// Methods XNameContainer
void NameContainer::insertByName(const OUString& aName, const Any& aElement,
                                 std::unique_lock<std::mutex>& guard)
{
    if (hasByName(aName))
        throw ElementExistException(aName);
    insertNoCheck(aName, aElement, guard);
}

void NameContainer::removeByName(const OUString& aName, std::unique_lock<std::mutex>& guard)
{
    auto aIt = maMap.find(aName);
    if (aIt == maMap.end())
    {
        throw NoSuchElementException("\"" + aName + "\" not found");
    }

    Any aOldElement = aIt->second;
    maMap.erase(aIt);

    // Fire event
    if (maContainerListeners.getLength(guard) > 0)
    {
        ContainerEvent aEvent;
        aEvent.Source = mpxEventSource;
        aEvent.Accessor <<= aName;
        aEvent.Element = aOldElement;
        maContainerListeners.notifyEach(guard, &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(guard) > 0)
    {
        ChangesEvent aEvent;
        aEvent.Source = mpxEventSource;
        aEvent.Base <<= aEvent.Source;
        aEvent.Changes = { { Any(aName),
                             {}, // Element remains empty (meaning "replaced with nothing")
                             aOldElement } };
        maChangesListeners.notifyEach(guard, &XChangesListener::changesOccurred, aEvent);
    }
}


// Methods XContainer
void NameContainer::addContainerListener(const Reference<XContainerListener>& xListener,
                                         std::unique_lock<std::mutex>& guard)
{
    if( !xListener.is() )
    {
        throw RuntimeException(u"addContainerListener called with null xListener"_ustr,rOwner);
    }
    maContainerListeners.addInterface(guard, xListener);
}

void NameContainer::removeContainerListener(const Reference<XContainerListener>& xListener,
                                            std::unique_lock<std::mutex>& guard)
{
    if( !xListener.is() )
    {
        throw RuntimeException(u"removeContainerListener called with null xListener"_ustr,rOwner);
    }
    maContainerListeners.removeInterface(guard, xListener);
}

// Methods XChangesNotifier
void NameContainer::addChangesListener(const Reference<XChangesListener>& xListener,
                                       std::unique_lock<std::mutex>& guard)
{
    if( !xListener.is() )
    {
        throw RuntimeException(u"addChangesListener called with null xListener"_ustr,rOwner);
    }
    maChangesListeners.addInterface(guard, xListener);
}

void NameContainer::removeChangesListener(const Reference<XChangesListener>& xListener,
                                          std::unique_lock<std::mutex>& guard)
{
    if( !xListener.is() )
    {
        throw RuntimeException(u"removeChangesListener called with null xListener"_ustr,rOwner);
    }
    maChangesListeners.removeInterface(guard, xListener);
}


// ModifiableHelper

void ModifiableHelper::setModified(bool _bModified, std::unique_lock<std::mutex>& guard)
{
    if ( _bModified == mbModified )
    {
        return;
    }
    mbModified = _bModified;

    if (m_aModifyListeners.getLength(guard) == 0)
    {
        return;
    }
    EventObject aModifyEvent( m_rEventSource );
    m_aModifyListeners.notifyEach(guard, &XModifyListener::modified, aModifyEvent);
}


// Ctor
SfxLibraryContainer::SfxLibraryContainer()
    : mnRunningVBAScripts( 0 )
    , mbVBACompat( false )
    , meVBATextEncoding( RTL_TEXTENCODING_DONTKNOW )
    , maModifiable( *this )
    , maNameContainer( cppu::UnoType<XNameAccess>::get(), *this )
    , mpBasMgr( nullptr )
    , mbOwnBasMgr( false )
    , mbOldInfoFormat( false )
    , mbOasis2OOoFormat( 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 (m_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(u"no root storage"_ustr, getXWeak(), 1);
    }
    mxStorage = _rxRootStorage;
    onNewRootStorage();
}

void SAL_CALL SfxLibraryContainer::storeLibrariesToStorage( const Reference< XStorage >&&nbsp;_rxRootStorage )
{
    LibraryContainerMethodGuard aGuard( *this );
    if ( !_rxRootStorage.is() )
    {
        throw IllegalArgumentException(u"no root storage"_ustr, getXWeak(), 1);
    }
    try
    {
        storeLibraries_Impl(_rxRootStorage, true, o3tl::temporary(std::unique_lock(m_aMutex)));
    }
    catchconst 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
    for (auto& aName : maNameContainer.getElementNames())
    {
        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, o3tl::temporary(std::unique_lock(m_aMutex)));
}

void SAL_CALL SfxLibraryContainer::addModifyListener( const Reference< XModifyListener >&&nbsp;_rxListener )
{
    LibraryContainerMethodGuard aGuard( *this );
    maModifiable.addModifyListener(_rxListener, o3tl::temporary(std::unique_lock(m_aMutex)));
}

void SAL_CALL SfxLibraryContainer::removeModifyListener( const Reference< XModifyListener >& _rxListener )
{
    LibraryContainerMethodGuard aGuard( *this );
    maModifiable.removeModifyListener(_rxListener, o3tl::temporary(std::unique_lock(m_aMutex)));
}

// 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(), o3tl::temporary(std::unique_lock(m_aMutex)));
        // 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
    }
    catchconst Exception& )
    {
        throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
    }
}

namespace
{
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 );
    }
}

constexpr OUString sUserBasicVariablePrefix = u"$(USER)/basic/"_ustr;
constexpr OUString sInstBasicVariablePrefix = u"$(INST)/" LIBO_SHARE_FOLDER "/basic/"_ustr;

void createVariableURL( OUString& rStr, std::u16string_view rLibName,
                               std::u16string_view rInfoFileName, bool bUser )
{
    if( bUser )
    {
        rStr = sUserBasicVariablePrefix;
    }
    else
    {
        rStr = sInstBasicVariablePrefix;
    }
    rStr += OUString::Concat(rLibName) + "/" + rInfoFileName + ".xlb/";
}
}

void SfxLibraryContainer::init(const OUString& rInitialDocumentURL,
                               const uno::Reference<embed::XStorage>& rxInitialStorage,
                               std::unique_lock<std::mutex>& guard)
{
    // 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, guard);
    osl_atomic_decrement( &m_refCount );
}

void SfxLibraryContainer::init_Impl( const OUString& rInitialDocumentURL,
                                     const uno::Reference< embed::XStorage >& rxInitialStorage,
                                     std::unique_lock<std::mutex>& guard )
{
    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( std::move(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, guard);
            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;
    }
    forint 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
            ::xmlscript::LibDescriptorArray aLibArray;

            Reference< XParser > xParser = xml::sax::Parser::create(mxContext);
            try
            {
                xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( &aLibArray ) );
                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 = aLibArray.mnLibCount;
            for( sal_Int32 i = 0 ; i < nLibCount ; i++ )
            {
                ::xmlscript::LibDescriptor& rLib = aLibArray.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, guard);
                    }
                    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, guard);
                        }
                        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_Impl(aLibName, rLib.aStorageURL, rLib.bReadOnly, guard);
                    pImplLib = static_cast< SfxLibrary* >( xLib.get() );
                }
                else
                {
                    Reference<XNameContainer> xLib = createLibrary_Impl(aLibName, guard);
                    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, guard);

                // 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_Impl()
                    if( !pImplLib->mbInitialised && (!bStorage || xLibraryStor.is()) )
                    {
                        bool bLoaded = implLoadLibraryIndexFile( pImplLib, rLib, xLibraryStor, OUString(), guard );
                        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, guard);

                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(guard);
        }
        catch(const uno::Exception& )
        {
            // TODO: error handling?
            SAL_WARN("basic""Cannot access extensions!");
        }
    }

    // Preload?
    {
        for (auto& aName : maNameContainer.getElementNames())
        {
            SfxLibrary* pImplLib = getImplLib( aName );
            if( pImplLib->mbPreload )
            {
                loadLibrary_Impl(aName, guard);
            }
        }
    }

    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(u"Standard"_ustr);

    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( u"xlb"_ustr );
                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 );

            for (auto& aLibName : pPrevCont->getElementNames())
            {
                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_Impl( aLibName, pImplLib->maStorageURL, pImplLib->mbReadOnly, guard );
                    }
                }
                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, guard);
                    }

                    // Create library
                    Reference<XNameContainer> xLib = createLibrary_Impl(aLibName, guard);
                    SfxLibrary* pNewLib = static_cast< SfxLibrary* >( xLib.get() );
                    pNewLib->mbLoaded = false;
                    pNewLib->implSetModified(false, guard);
                    checkStorageURL( aLibFolder, pNewLib->maLibInfoFileURL,
                                     pNewLib->maStorageURL, pNewLib->maUnexpandedStorageURL );

                    uno::Reference< embed::XStorage > xDummyStor;
                    ::xmlscript::LibDescriptor aLibDesc;
                    implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, pNewLib->maLibInfoFileURL, guard );
                    implImportLibDescriptor(pNewLib, aLibDesc, guard);
                }
            }
            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(std::move(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(std::unique_lock<std::mutex>& guard)
{
#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_Impl(aLibName, aIndexFileURL, bReadOnly, guard);
    }
#else
    (void)guard;
#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;
    }
    else
    {
        // try to re-create the variable URL: helps moving the profile
        if (std::u16string_view aRest; aSourceURL.startsWith(expand_url(sUserBasicVariablePrefix), &aRest))
            aUnexpandedStorageURL = sUserBasicVariablePrefix + aRest;
        else if (aSourceURL.startsWith(expand_url(sInstBasicVariablePrefix), &aRest))
            aUnexpandedStorageURL = sInstBasicVariablePrefix + aRest;
        else
            aUnexpandedStorageURL.clear(); // This will use eventual value of aLibInfoFileURL
    }

    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 )
{
    auto xNameAccess = maNameContainer.getByName(rLibraryName).query<XNameAccess>();
    return static_cast<SfxLibrary*>(xNameAccess.get());
}


// 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*/,
    std::unique_lock<std::mutex>& /*guard*/ )
{
    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;

    if( bStorage )
    {
        for (auto& aElementName : pLib->getElementNames())
        {
            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(u"MediaType"_ustr, uno::Any( u"text/xml"_ustr ) );

                    // #87671 Allow encryption
                    xProps->setPropertyValue(u"UseCommonStoragePasswordEncryption"_ustr, 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 (auto& aElementName : pLib->getElementNames())
            {
                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(u"MediaType"_ustr, uno::Any( u"text/xml"_ustr ) );

                // #87671 Allow encryption
                xProps->setPropertyValue(u"UseCommonStoragePasswordEncryption"_ustr, 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,
                                                     std::unique_lock<std::mutex>& guard )
{
    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 = std::move(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_Impl(rLib.aName, guard);
        pLib = static_cast< SfxLibrary* >( xLib.get() );
        pLib->mbLoaded = false;
        rLib.aStorageURL = aIndexFileName;
        checkStorageURL( rLib.aStorageURL, pLib->maLibInfoFileURL, pLib->maStorageURL,
                         pLib->maUnexpandedStorageURL );

        implImportLibDescriptor(pLib, rLib, guard);
    }

    return true;
}

void SfxLibraryContainer::implImportLibDescriptor( SfxLibrary* pLib,
                                                  ::xmlscript::LibDescriptor const& rLib,
                                                  std::unique_lock<std::mutex>& guard)
{
    if( pLib->mbInitialised )
        return;
    Any aDummyElement = createEmptyLibraryElement();
    for (auto& name : rLib.aElementNames)
    {
        pLib->maNameContainer.insertByName(name, aDummyElement, guard);
    }
    pLib->mbPasswordProtected = rLib.bPasswordProtected;
    pLib->mbReadOnly = rLib.bReadOnly;
    pLib->mbPreload  = rLib.bPreload;
    pLib->implSetModified(false, guard);
    pLib->mbInitialised = true;
}


// Methods of new XLibraryStorage interface?
void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference< embed::XStorage >&&nbsp;i_rStorage,
                                               bool bComplete, std::unique_lock<std::mutex>& guard )
{
    const Sequence< OUString > aNames = maNameContainer.getElementNames();

    // Don't count libs from shared index file
    sal_Int32 nLibsToSave
        = std::count_if(aNames.begin(), aNames.end(),
                        [this](const OUString& name) {
                            SfxLibrary* pImplLib = getImplLib(name);
                            return !pImplLib->mbSharedIndexFile && !pImplLib->mbExtension;
                        });
    // 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" ) )
        {
            if (!getImplLib(aNames[0])->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 OUString aTempTargetNameBase = maLibrariesDir + "_temp_";
                sal_Int32 index = 0;
                do
                {
                    sTargetLibrariesStoreName = aTempTargetNameBase + OUString::number( index++ );
                    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 );
        }
        catchconst 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 );
            }
        }
        catchconst uno::Exception& )
        {
            DBG_UNHANDLED_EXCEPTION("basic");
            return;
        }
    }

    int iArray = 0;
    ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs;
    ::xmlscript::LibDescriptorArray aLibArray( nLibsToSave );
    for (auto& name : aNames)
    {
        SfxLibrary* pImplLib = getImplLib(name);
        if( pImplLib->mbSharedIndexFile )
        {
            continue;
        }
        const bool bExtensionLib = pImplLib->mbExtension;
        ::xmlscript::LibDescriptor& rLib = bExtensionLib ?
              aLibDescriptorForExtensionLibs : aLibArray.mpLibs[iArray];
        if( !bExtensionLib )
        {
            iArray++;
        }
        rLib.aName = name;

        rLib.bLink = pImplLib->mbLink;
        if( !bStorage || pImplLib->mbLink )
        {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=93 H=99 G=95

¤ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.