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

Quelle  filedlghelper.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 <memory>
#include <optional>
#include <string_view>
#include <o3tl/test_info.hxx>

#include <sfx2/filedlghelper.hxx>
#include <sal/types.h>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/ControlActions.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
#include <com/sun/star/ui/dialogs/FolderPicker.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XControlInformation.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/task/InteractionHandler.hpp>
#include <com/sun/star/task/XInteractionRequest.hpp>
#include <com/sun/star/util/RevisionTag.hpp>
#include <comphelper/fileurl.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/string.hxx>
#include <comphelper/types.hxx>
#include <tools/urlobj.hxx>
#include <vcl/help.hxx>
#include <vcl/weld.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/ucbhelper.hxx>
#include <osl/file.hxx>
#include <osl/security.hxx>
#include <vcl/mnemonic.hxx>
#include <vcl/svapp.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/saveopt.hxx>
#include <unotools/securityoptions.hxx>
#include <svl/itemset.hxx>
#include <svl/eitem.hxx>
#include <svl/intitem.hxx>
#include <vcl/dibtools.hxx>
#include <vcl/graphicfilter.hxx>
#include <unotools/filteroptions_settings.hxx>
#include <unotools/viewoptions.hxx>
#include <svtools/helpids.h>
#include <comphelper/docpasswordrequest.hxx>
#include <comphelper/docpasswordhelper.hxx>
#include <ucbhelper/content.hxx>
#include <comphelper/storagehelper.hxx>
#include <sfx2/app.hxx>
#include <sfx2/frame.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/sfxresid.hxx>
#include <sfx2/sfxsids.hrc>
#include <guisaveas.hxx>
#include "filtergrouping.hxx"
#include "filedlgimpl.hxx"
#include <fpicker/fpsofficeResMgr.hxx>
#include <fpicker/strings.hrc>
#include <sfx2/strings.hrc>
#include <sal/log.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <o3tl/string_view.hxx>
#include <officecfg/Office/Common.hxx>

#include <config_gpgme.h>
#if HAVE_FEATURE_GPGME
include <com/sun/star/xml/crypto/SEInitializer.hpp>
include <com/sun/star/xml/crypto/GPGSEInitializer.hpp>
include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
#endif
#include <comphelper/xmlsechelper.hxx>
#include <unotools/useroptions.hxx>

#ifdef UNX
#include <errno.h>
#include <sys/stat.h>
#endif

using namespace ::com::sun::star;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::ui::dialogs;
using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::cppu;

constexpr OUString IODLG_CONFIGNAME = u"FilePicker_Save"_ustr;
constexpr OUString IMPGRF_CONFIGNAME = u"FilePicker_Graph"_ustr;
constexpr OUString USERITEM_NAME = u"UserItem"_ustr;

namespace sfx2
{

namespace
{
    bool lclSupportsOOXMLEncryption(std::u16string_view aFilterName)
    {
        return  aFilterName == u"Calc MS Excel 2007 XML"
                ||  aFilterName == u"MS Word 2007 XML"
                ||  aFilterName == u"Impress MS PowerPoint 2007 XML"
                ||  aFilterName == u"Impress MS PowerPoint 2007 XML AutoPlay"
                ||  aFilterName == u"Calc Office Open XML"
                ||  aFilterName == u"Impress Office Open XML"
                ||  aFilterName == u"Impress Office Open XML AutoPlay"
                ||  aFilterName == u"Office Open XML Text";
    }
}

static std::optional<OUString> GetLastFilterConfigId( FileDialogHelper::Context _eContext )
{
    static constexpr OUStringLiteral aSD_EXPORT_IDENTIFIER(u"SdExportLastFilter");
    static constexpr OUStringLiteral aSI_EXPORT_IDENTIFIER(u"SiExportLastFilter");
    static constexpr OUStringLiteral aSW_EXPORT_IDENTIFIER(u"SwExportLastFilter");

    switch( _eContext )
    {
        case FileDialogHelper::DrawExport: return aSD_EXPORT_IDENTIFIER;
        case FileDialogHelper::ImpressExport: return aSI_EXPORT_IDENTIFIER;
        case FileDialogHelper::WriterExport: return aSW_EXPORT_IDENTIFIER;
        defaultbreak;
    }

    return {};
}

static OUString EncodeSpaces_Impl( const OUString& rSource );
static OUString DecodeSpaces_Impl( const OUString& rSource );

// FileDialogHelper_Impl

// XFilePickerListener Methods
void SAL_CALL FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent& ;)
{
    SolarMutexGuard aGuard;
    mpAntiImpl->FileSelectionChanged();
}

void SAL_CALL FileDialogHelper_Impl::directoryChanged( const FilePickerEvent& )
{
    SolarMutexGuard aGuard;
    mpAntiImpl->DirectoryChanged();
}

OUString SAL_CALL FileDialogHelper_Impl::helpRequested( const FilePickerEvent& aEvent )
{
    SolarMutexGuard aGuard;
    return sfx2::FileDialogHelper::HelpRequested( aEvent );
}

void SAL_CALL FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent& aEvent )
{
    SolarMutexGuard aGuard;
    mpAntiImpl->ControlStateChanged( aEvent );
}

void SAL_CALL FileDialogHelper_Impl::dialogSizeChanged()
{
    SolarMutexGuard aGuard;
    mpAntiImpl->DialogSizeChanged();
}

// XDialogClosedListener Methods
void SAL_CALL FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent& _rEvent )
{
    SolarMutexGuard aGuard;
    mpAntiImpl->DialogClosed( _rEvent );
    postExecute( _rEvent.DialogResult );
}

// handle XFilePickerListener events
void FileDialogHelper_Impl::handleFileSelectionChanged()
{
    if ( mbHasVersions )
        updateVersions();

    if ( mbShowPreview )
        maPreviewIdle.Start();
}

void FileDialogHelper_Impl::handleDirectoryChanged()
{
    if ( mbShowPreview )
        TimeOutHdl_Impl( nullptr );
}

OUString FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent& aEvent )
{
    TranslateId aHelpId;

    // mapping from element id -> help id
    switch ( aEvent.ElementId )
    {
        case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
            aHelpId = STR_FILESAVE_AUTOEXTENSION;
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
            aHelpId = STR_FILESAVE_SAVEWITHPASSWORD;
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
            aHelpId = STR_FILESAVE_CUSTOMIZEFILTER;
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_READONLY :
            aHelpId = STR_FILEOPEN_READONLY;
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_LINK :
            aHelpId = STR_FILEDLG_LINK_CB;
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW :
            aHelpId = STR_FILEDLG_PREVIEW_CB;
            break;

        case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
            aHelpId = STR_FILESAVE_DOPLAY;
            break;

        case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL :
        case ExtendedFilePickerElementIds::LISTBOX_VERSION :
            aHelpId = STR_FILEOPEN_VERSION;
            break;

        case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL :
        case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
            aHelpId = STR_FILESAVE_TEMPLATE;
            break;

        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL :
        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
            aHelpId = STR_FILEOPEN_IMAGE_TEMPLATE;
            break;

        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR_LABEL :
        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR :
            aHelpId = STR_FILEOPEN_IMAGE_ANCHOR;
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
            aHelpId = STR_FILESAVE_SELECTION;
            break;

        default:
            SAL_WARN( "sfx.dialog""invalid element id" );
    }

    return aHelpId ? FpsResId(aHelpId) : OUString();
}

void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent& aEvent )
{
    switch ( aEvent.ElementId )
    {
        case CommonFilePickerElementIds::LISTBOX_FILTER:
            updateFilterOptionsBox();
            enablePasswordBox( false );
            enableGpgEncrBox( false );
            updateSelectionBox();
            updateSignByDefault();
            // only use it for export and with our own dialog
            if ( mbExport && !mbSystemPicker )
                updateExportButton();
            break;

        case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW:
            updatePreviewState(true);
            break;
    }
}

void FileDialogHelper_Impl::handleDialogSizeChanged()
{
    if ( mbShowPreview )
        TimeOutHdl_Impl( nullptr );
}

// XEventListener Methods
void SAL_CALL FileDialogHelper_Impl::disposing( const EventObject& )
{
    SolarMutexGuard aGuard;
    dispose();
}

void FileDialogHelper_Impl::dispose()
{
    if ( mxFileDlg.is() )
    {
        // remove the event listener
        mxFileDlg->removeFilePickerListener( this );

        ::comphelper::disposeComponent( mxFileDlg );
        mxFileDlg.clear();
    }
}

OUString FileDialogHelper_Impl::getCurrentFilterUIName() const
{
    OUString aFilterName;

    if( mxFileDlg.is() )
    {
        aFilterName = mxFileDlg->getCurrentFilter();

        if ( !aFilterName.isEmpty() && isShowFilterExtensionEnabled() )
            aFilterName = getFilterName( aFilterName );
    }

    return aFilterName;
}

void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString& _rContextIdentifier )
{
    SvtViewOptions aDlgOpt( EViewType::Dialog, IODLG_CONFIGNAME );

    if( aDlgOpt.Exists() )
    {
        OUString    aLastFilter;
        if( aDlgOpt.GetUserItem( _rContextIdentifier ) >>= aLastFilter )
            setFilter( aLastFilter );
    }
}

void FileDialogHelper_Impl::SaveLastUsedFilter()
{
    std::optional<OUString> pConfigId = GetLastFilterConfigId( meContext );
    if( pConfigId )
        SvtViewOptions( EViewType::Dialog, IODLG_CONFIGNAME ).SetUserItem( *pConfigId,
                            Any( getFilterWithExtension( getFilter() ) ) );
}

std::shared_ptr<const SfxFilter> FileDialogHelper_Impl::getCurrentSfxFilter()
{
    OUString aFilterName = getCurrentFilterUIName();

    if ( mpMatcher && !aFilterName.isEmpty() )
        return mpMatcher->GetFilter4UIName( aFilterName, m_nMustFlags, m_nDontFlags );

    return nullptr;
}

bool FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId, bool _bEnable )
{
    bool bIsEnabled = false;

    uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
    if ( xCtrlAccess.is() )
    {
        try
        {
            xCtrlAccess->enableControl( _nExtendedControlId, _bEnable );
            bIsEnabled = _bEnable;
        }
        catchconst IllegalArgumentException& )
        {
            TOOLS_WARN_EXCEPTION( "sfx""FileDialogHelper_Impl::updateExtendedControl" );
        }
    }
    return bIsEnabled;
}

bool FileDialogHelper_Impl::CheckFilterOptionsCapability( const std::shared_ptr<const SfxFilter>& _pFilter )
{
    bool bResult = false;

    if( mxFilterCFG.is() && _pFilter )
    {
        try
        {
            Sequence < PropertyValue > aProps;
            Any aAny = mxFilterCFG->getByName( _pFilter->GetName() );
            if ( aAny >>= aProps )
            {
                OUString aServiceName;
                for (const auto& rProp : aProps)
                {
                    if( rProp.Name == "UIComponent" )
                    {
                        rProp.Value >>= aServiceName;
                        if( !aServiceName.isEmpty() )
                            bResult = true;
                    }
                }
            }
        }
        catchconst Exception& )
        {
        }
    }

    return bResult;
}

bool FileDialogHelper_Impl::isInOpenMode() const
{
    bool bRet = false;

    switch ( m_nDialogType )
    {
        case FILEOPEN_SIMPLE:
        case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
        case FILEOPEN_PLAY:
        case FILEOPEN_LINK_PLAY:
        case FILEOPEN_READONLY_VERSION:
        case FILEOPEN_READONLY_VERSION_FILTEROPTIONS:
        case FILEOPEN_LINK_PREVIEW:
        case FILEOPEN_PREVIEW:
            bRet = true;
    }

    return bRet;
}

void FileDialogHelper_Impl::updateFilterOptionsBox()
{
    if ( !m_bHaveFilterOptions )
        return;

    bool bFilterOptionsEnabled = CheckFilterOptionsCapability(getCurrentSfxFilter());

    updateExtendedControl(ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS,
                          bFilterOptionsEnabled);

    if (isInOpenMode())
    {
        if (auto xCtrlAccess = mxFileDlg.query<XFilePickerControlAccess>())
        {
            OUString filter;
            getRealFilter(filter);
            bool bChecked = bFilterOptionsEnabled && utl::isShowFilterOptionsDialog(filter);
            xCtrlAccess->setValue(ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, 0,
                                  Any(bChecked));
        }
    }
}

void FileDialogHelper_Impl::updateExportButton()
{
    uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
    if ( !xCtrlAccess.is() )
        return;

    OUString sOldLabel( xCtrlAccess->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK ) );

    // initialize button label; we need the label with the mnemonic char
    if ( maButtonLabel.isEmpty() || maButtonLabel.indexOf( MNEMONIC_CHAR ) == -1 )
    {
        // cut the ellipses, if necessary
        sal_Int32 nIndex = sOldLabel.indexOf( "..." );
        if ( -1 == nIndex )
            nIndex = sOldLabel.getLength();
        maButtonLabel = sOldLabel.copy( 0, nIndex );
    }

    OUString sLabel = maButtonLabel;
    // filter with options -> append ellipses on export button label
    if ( CheckFilterOptionsCapability( getCurrentSfxFilter() ) )
        sLabel += "...";

    if ( sOldLabel != sLabel )
    {
        try
        {
            xCtrlAccess->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK, sLabel );
        }
        catchconst IllegalArgumentException& )
        {
            TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::updateExportButton" );
        }
    }
}

void FileDialogHelper_Impl::updateSelectionBox()
{
    if ( !mbHasSelectionBox )
        return;

    // Does the selection box exist?
    bool bSelectionBoxFound = false;
    uno::Reference< XControlInformation > xCtrlInfo( mxFileDlg, UNO_QUERY );
    if ( xCtrlInfo.is() )
    {
        Sequence< OUString > aCtrlList = xCtrlInfo->getSupportedControls();
        bSelectionBoxFound = comphelper::findValue(aCtrlList, "SelectionBox") != -1;
    }

    if ( bSelectionBoxFound )
    {
        std::shared_ptr<const SfxFilter> pFilter = getCurrentSfxFilter();
        mbSelectionFltrEnabled = updateExtendedControl(
            ExtendedFilePickerElementIds::CHECKBOX_SELECTION,
            ( mbSelectionEnabled && pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::SUPPORTSSELECTION ) ) );
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
        xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, Any( mbSelection ) );
    }
}

void FileDialogHelper_Impl::updateSignByDefault()
{
#if HAVE_FEATURE_GPGME
    if (!mbHasSignByDefault)
        return;

    OUString aSigningKey = SvtUserOptions{}.GetSigningKey();
    updateExtendedControl(ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN, !aSigningKey.isEmpty());
#endif
}

void FileDialogHelper_Impl::enablePasswordBox( bool bInit )
{
    if ( ! mbHasPassword )
        return;

    // in case of initialization assume previous state to be false
    bool bWasEnabled = !bInit && mbIsPwdEnabled;

    std::shared_ptr<const SfxFilter> pCurrentFilter = getCurrentSfxFilter();
    mbIsPwdEnabled = updateExtendedControl(
        ExtendedFilePickerElementIds::CHECKBOX_PASSWORD,
        pCurrentFilter && ( pCurrentFilter->GetFilterFlags() & SfxFilterFlags::ENCRYPTION )
    );

    if( !bWasEnabled && mbIsPwdEnabled )
    {
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
        if( mbPwdCheckBoxState )
            xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, Any( true ) );
    }
    else if( bWasEnabled && !mbIsPwdEnabled )
    {
        // remember user settings until checkbox is enabled
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
        Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
        bool bPassWord = false;
        mbPwdCheckBoxState = ( aValue >>= bPassWord ) && bPassWord;
        xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, Any( false ) );
    }
}

void FileDialogHelper_Impl::enableGpgEncrBox( bool bInit )
{
    if ( ! mbHasPassword )  // CHECKBOX_GPGENCRYPTION is visible if CHECKBOX_PASSWORD is visible
        return;

    // in case of initialization assume previous state to be false
    bool bWasEnabled = !bInit && mbIsGpgEncrEnabled;

    std::shared_ptr<const SfxFilter> pCurrentFilter = getCurrentSfxFilter();
    mbIsGpgEncrEnabled = updateExtendedControl(
        ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION,
        pCurrentFilter && ( pCurrentFilter->GetFilterFlags() & SfxFilterFlags::GPGENCRYPTION )
    );

    if( !bWasEnabled && mbIsGpgEncrEnabled )
    {
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
        if( mbGpgCheckBoxState )
            xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0, Any( true ) );
    }
    else if( bWasEnabled && !mbIsGpgEncrEnabled )
    {
        // remember user settings until checkbox is enabled
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
        Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0 );
        bool bGpgEncryption = false;
        mbGpgCheckBoxState = ( aValue >>= bGpgEncryption ) && bGpgEncryption;
        xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0, Any( false ) );
    }
}

void FileDialogHelper_Impl::updatePreviewState( bool _bUpdatePreviewWindow )
{
    if ( !mbHasPreview )
        return;

    uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );

    // check, whether or not we have to display a preview
    if ( !xCtrlAccess.is() )
        return;

    try
    {
        Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 );
        bool bShowPreview = false;

        if ( aValue >>= bShowPreview )
        {
            mbShowPreview = bShowPreview;

            // setShowState has currently no effect for the
            // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
            uno::Reference< XFilePreview > xFilePreview( mxFileDlg, UNO_QUERY );
            if ( xFilePreview.is() )
                xFilePreview->setShowState( mbShowPreview );

            if ( _bUpdatePreviewWindow )
                TimeOutHdl_Impl( nullptr );
        }
    }
    catchconst Exception& )
    {
        TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::updatePreviewState" );
    }
}

void FileDialogHelper_Impl::updateVersions()
{
    Sequence < OUString > aEntries;
    Sequence < OUString > aPathSeq = mxFileDlg->getSelectedFiles();

    if ( aPathSeq.getLength() == 1 )
    {
        INetURLObject aObj( aPathSeq[0] );

        if ( ( aObj.GetProtocol() == INetProtocol::File ) &&
            ( utl::UCBContentHelper::IsDocument( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) )
        {
            try
            {
                uno::Reference< embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
                                                                aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
                                                                embed::ElementModes::READ );

                DBG_ASSERT( xStorage.is(), "The method must return the storage or throw exception!" );
                if ( !xStorage.is() )
                    throw uno::RuntimeException();

                const uno::Sequence < util::RevisionTag > xVersions = SfxMedium::GetVersionList( xStorage );

                aEntries.realloc( xVersions.getLength() + 1 );
                aEntries.getArray()[0] = SfxResId( STR_SFX_FILEDLG_ACTUALVERSION );

                std::transform(xVersions.begin(), xVersions.end(), std::next(aEntries.getArray()),
                    [](const util::RevisionTag& rVersion) -> OUString { return rVersion.Identifier; });
            }
            catchconst uno::Exception& )
            {
            }
        }
    }

    uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
    Any aValue;

    try
    {
        xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
                        ControlActions::DELETE_ITEMS, aValue );
    }
    catchconst IllegalArgumentException& ){}

    if ( !aEntries.hasElements() )
        return;

    try
    {
        aValue <<= aEntries;
        xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
                        ControlActions::ADD_ITEMS, aValue );

        Any aPos;
        aPos <<= sal_Int32(0);
        xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
                        ControlActions::SET_SELECT_ITEM, aPos );
    }
    catchconst IllegalArgumentException& ){}
}

IMPL_LINK_NOARG(FileDialogHelper_Impl, TimeOutHdl_Impl, Timer *, void)
{
    if ( !mbHasPreview )
        return;

    maGraphic.Clear();

    Any aAny;
    uno::Reference < XFilePreview > xFilePicker( mxFileDlg, UNO_QUERY );

    if ( ! xFilePicker.is() )
        return;

    Sequence < OUString > aPathSeq = mxFileDlg->getSelectedFiles();

    if ( mbShowPreview && ( aPathSeq.getLength() == 1 ) )
    {
        const OUString&    aURL = aPathSeq[0];

        if ( ERRCODE_NONE == getGraphic( aURL, maGraphic ) )
        {
            // changed the code slightly;
            // before: the bitmap was scaled and
            // surrounded a white frame
            // now: the bitmap will only be scaled
            // and the filepicker implementation
            // is responsible for placing it at its
            // proper position and painting a frame

            BitmapEx aBmp = maGraphic.GetBitmapEx();
            if ( !aBmp.IsEmpty() )
            {
                // scale the bitmap to the correct size
                sal_Int32 nOutWidth  = xFilePicker->getAvailableWidth();
                sal_Int32 nOutHeight = xFilePicker->getAvailableHeight();
                sal_Int32 nBmpWidth  = aBmp.GetSizePixel().Width();
                sal_Int32 nBmpHeight = aBmp.GetSizePixel().Height();

                double nXRatio = static_cast<double>(nOutWidth) / nBmpWidth;
                double nYRatio = static_cast<double>(nOutHeight) / nBmpHeight;

                if ( nXRatio < nYRatio )
                    aBmp.Scale( nXRatio, nXRatio );
                else
                    aBmp.Scale( nYRatio, nYRatio );

                // Convert to true color, to allow CopyPixel
                aBmp.Convert( BmpConversion::N24Bit );

                // and copy it into the Any
                SvMemoryStream aData;

                WriteDIB(aBmp, aData, false);

                const Sequence < sal_Int8 > aBuffer(
                    static_castconst sal_Int8* >(aData.GetData()),
                    aData.GetEndOfData() );

                aAny <<= aBuffer;
            }
        }
    }

    try
    {
        SolarMutexReleaser aReleaseForCallback;
        // clear the preview window
        xFilePicker->setImage( FilePreviewImageFormats::BITMAP, aAny );
    }
    catchconst IllegalArgumentException& )
    {
    }
}

ErrCode FileDialogHelper_Impl::getGraphic( const OUString& rURL,
                                           Graphic& rGraphic ) const
{
    if ( utl::UCBContentHelper::IsFolder( rURL ) )
        return ERRCODE_IO_NOTAFILE;

    if ( !mpGraphicFilter )
        return ERRCODE_IO_NOTSUPPORTED;

    // select graphic filter from dialog filter selection
    OUString aCurFilter( getFilter() );

    sal_uInt16 nFilter = !aCurFilter.isEmpty() && mpGraphicFilter->GetImportFormatCount()
                    ? mpGraphicFilter->GetImportFormatNumber( aCurFilter )
                    : GRFILTER_FORMAT_DONTKNOW;

    INetURLObject aURLObj( rURL );

    if ( aURLObj.HasError() || INetProtocol::NotValid == aURLObj.GetProtocol() )
    {
        aURLObj.SetSmartProtocol( INetProtocol::File );
        aURLObj.SetSmartURL( rURL );
    }

    ErrCode nRet = ERRCODE_NONE;

    GraphicFilterImportFlags nFilterImportFlags = GraphicFilterImportFlags::SetLogsizeForJpeg;
    // non-local?
    if ( INetProtocol::File != aURLObj.GetProtocol() )
    {
        std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( rURL, StreamMode::READ );

        if( pStream )
            nRet = mpGraphicFilter->ImportGraphic( rGraphic, rURL, *pStream, nFilter, nullptr, nFilterImportFlags );
        else
            nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, nullptr, nFilterImportFlags );
    }
    else
    {
        nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, nullptr, nFilterImportFlags );
    }

    return nRet;
}

ErrCode FileDialogHelper_Impl::getGraphic( Graphic& rGraphic ) const
{
    ErrCode nRet = ERRCODE_NONE;

    // rhbz#1079672 do not return maGraphic, it needs not to be the selected file

    OUString aPath;
    Sequence<OUString> aPathSeq = mxFileDlg->getSelectedFiles();

    if (aPathSeq.getLength() == 1)
    {
        aPath = aPathSeq[0];
    }

    if (!aPath.isEmpty())
        nRet = getGraphic(aPath, rGraphic);
    else
        nRet = ERRCODE_IO_GENERAL;

    return nRet;
}

static bool lcl_isSystemFilePicker( const uno::Reference< XExecutableDialog >& _rxFP )
{
    try
    {
        uno::Reference< XServiceInfo > xSI( _rxFP, UNO_QUERY );
        if ( !xSI.is() )
            return true;
        return xSI->supportsService( u"com.sun.star.ui.dialogs.SystemFilePicker"_ustr );
    }
    catchconst Exception& )
    {
    }
    return false;
}

namespace {

bool lcl_isAsyncFilePicker( const uno::Reference< XExecutableDialog >& _rxFP )
{
    try
    {
        uno::Reference<XAsynchronousExecutableDialog> xSI(_rxFP, UNO_QUERY);
        return xSI.is();
    }
    catchconst Exception& )
    {
    }
    return false;
}

enum open_or_save_t {OPEN, SAVE, UNDEFINED};

}

static open_or_save_t lcl_OpenOrSave(sal_Int16 const nDialogType)
{
    switch (nDialogType)
    {
        case FILEOPEN_SIMPLE:
        case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
        case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR:
        case FILEOPEN_PLAY:
        case FILEOPEN_LINK_PLAY:
        case FILEOPEN_READONLY_VERSION:
        case FILEOPEN_READONLY_VERSION_FILTEROPTIONS:
        case FILEOPEN_LINK_PREVIEW:
        case FILEOPEN_PREVIEW:
            return OPEN;
        case FILESAVE_SIMPLE:
        case FILESAVE_AUTOEXTENSION_PASSWORD:
        case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
        case FILESAVE_AUTOEXTENSION_SELECTION:
        case FILESAVE_AUTOEXTENSION_TEMPLATE:
        case FILESAVE_AUTOEXTENSION:
            return SAVE;
        default:
            assert(false); // invalid dialog type
    }
    return UNDEFINED;
}

// FileDialogHelper_Impl

css::uno::Reference<css::awt::XWindow> FileDialogHelper_Impl::GetFrameInterface()
{
    if (mpFrameWeld)
        return mpFrameWeld->GetXWindow();
    return css::uno::Reference<css::awt::XWindow>();
}

FileDialogHelper_Impl::FileDialogHelper_Impl(
    FileDialogHelper* _pAntiImpl,
    sal_Int16 nDialogType,
    FileDialogFlags nFlags,
    sal_Int16 nDialog,
    weld::Window* pFrameWeld,
    const OUString& sPreselectedDir,
    const css::uno::Sequence< OUString >& rDenyList
    )
    :msPreselectedDir( sPreselectedDir )
    ,maPreviewIdle("sfx2 FileDialogHelper_Impl maPreviewIdle")
    ,m_nDialogType          ( nDialogType )
    ,meContext              ( FileDialogHelper::UnknownContext )
{
    const char* pServiceName=nullptr;
    switch (nDialog)
    {
        case SFX2_IMPL_DIALOG_SYSTEM:
        case SFX2_IMPL_DIALOG_OOO:
            pServiceName = "com.sun.star.ui.dialogs.OfficeFilePicker";
            break;
        case SFX2_IMPL_DIALOG_REMOTE:
            pServiceName = "com.sun.star.ui.dialogs.RemoteFilePicker";
            break;
        default:
            pServiceName = "com.sun.star.ui.dialogs.FilePicker";
            break;
    }

    OUString aService = OUString::createFromAscii( pServiceName );

    uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );

    // create the file open dialog
    // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION

    mpFrameWeld             = pFrameWeld;
    mpAntiImpl              = _pAntiImpl;
    mbHasAutoExt            = false;
    mbHasPassword           = false;
    mbHasSignByDefault      = false;
    m_bHaveFilterOptions    = false;
    mbIsPwdEnabled          = true;
    mbIsGpgEncrEnabled      = true;
    mbHasVersions           = false;
    mbHasPreview            = false;
    mbShowPreview           = false;
    mbDeleteMatcher         = false;
    mbInsert                = bool(nFlags & (FileDialogFlags::Insert|
                                             FileDialogFlags::InsertCompare|
                                             FileDialogFlags::InsertMerge));
    mbExport                = bool(nFlags & FileDialogFlags::Export);
    mbIsSaveDlg             = false;
    mbPwdCheckBoxState      = false;
    mbGpgCheckBoxState      = false;
    mbSelection             = false;
    mbSelectionEnabled      = true;
    mbHasSelectionBox       = false;
    mbSelectionFltrEnabled  = false;

    // default settings
    m_nDontFlags = SFX_FILTER_NOTINSTALLED | SfxFilterFlags::INTERNAL | SfxFilterFlags::NOTINFILEDLG;
    if (OPEN == lcl_OpenOrSave(m_nDialogType))
        m_nMustFlags = SfxFilterFlags::IMPORT;
    else
        m_nMustFlags = SfxFilterFlags::EXPORT;


    mpMatcher = nullptr;
    mpGraphicFilter = nullptr;

    // create the picker component
    mxFileDlg.set(xFactory->createInstance( aService ), css::uno::UNO_QUERY);
    mbSystemPicker = lcl_isSystemFilePicker( mxFileDlg );
    mbAsyncPicker = lcl_isAsyncFilePicker(mxFileDlg);

    if ( ! mxFileDlg.is() )
    {
        return;
    }

    uno::Reference< XInitialization > xInit( mxFileDlg, UNO_QUERY );
    if ( xInit.is() )
    {
        sal_Int16 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE;

        switch ( m_nDialogType )
        {
            case FILEOPEN_SIMPLE:
                nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE;
                break;

            case FILESAVE_SIMPLE:
                nTemplateDescription = TemplateDescription::FILESAVE_SIMPLE;
                mbIsSaveDlg = true;
                break;

            case FILESAVE_AUTOEXTENSION_PASSWORD:
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD;
                mbHasPassword = true;
                mbHasAutoExt = true;
                mbIsSaveDlg = true;
                mbHasSignByDefault = true;
                break;

            case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS;
                mbHasPassword = true;

                m_bHaveFilterOptions = true;
                if( xFactory.is() )
                {
                    mxFilterCFG.set(
                        xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ),
                        UNO_QUERY );
                }

                mbHasAutoExt = true;
                mbIsSaveDlg = true;
                mbHasSignByDefault = true;
                break;

            case FILESAVE_AUTOEXTENSION_SELECTION:
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION;
                mbHasAutoExt = true;
                mbIsSaveDlg = true;
                mbHasSelectionBox = true;
                if ( mbExport && !mxFilterCFG.is() && xFactory.is() )
                {
                    mxFilterCFG.set(
                        xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ),
                        UNO_QUERY );
                }
                break;

            case FILESAVE_AUTOEXTENSION_TEMPLATE:
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE;
                mbHasAutoExt = true;
                mbIsSaveDlg = true;
                break;

            case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE;
                mbHasPreview = true;
                break;

            case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR:
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR;
                mbHasPreview = true;
                break;

            case FILEOPEN_PLAY:
                nTemplateDescription = TemplateDescription::FILEOPEN_PLAY;
                break;

            case FILEOPEN_LINK_PLAY:
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PLAY;
                break;

            case FILEOPEN_READONLY_VERSION:
                nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION;
                mbHasVersions = true;
                break;

            case FILEOPEN_READONLY_VERSION_FILTEROPTIONS:
                nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION_FILTEROPTIONS;
                m_bHaveFilterOptions = true;
                if( xFactory.is() )
                {
                    mxFilterCFG.set(
                        xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ),
                        UNO_QUERY );
                }
                mbHasVersions = true;
                break;

            case FILEOPEN_LINK_PREVIEW:
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW;
                mbHasPreview = true;
                break;

            case FILESAVE_AUTOEXTENSION:
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION;
                mbHasAutoExt = true;
                mbIsSaveDlg = true;
                break;

            case FILEOPEN_PREVIEW:
                nTemplateDescription = TemplateDescription::FILEOPEN_PREVIEW;
                mbHasPreview = true;
                break;

            default:
                SAL_WARN( "sfx.dialog""FileDialogHelper::ctor with unknown type" );
                break;
        }

        if (mbHasPreview)
        {
            maPreviewIdle.SetPriority( TaskPriority::LOWEST );
            maPreviewIdle.SetInvokeHandler( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) );
        }

        auto xWindow = GetFrameInterface();

        Sequence < Any > aInitArguments(!xWindow.is() ? 2 : 3);
        auto pInitArguments = aInitArguments.getArray();

        // This is a hack. We currently know that the internal file picker implementation
        // supports the extended arguments as specified below.
        // TODO:
        // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
        // b) adjust the implementation of the system file picker to that it recognizes it
        if ( mbSystemPicker )
        {
            pInitArguments[0] <<= nTemplateDescription;
            if (xWindow.is())
                pInitArguments[1] <<= xWindow;
        }
        else
        {
            pInitArguments[0] <<= NamedValue(
                                    u"TemplateDescription"_ustr,
                                    Any( nTemplateDescription )
                                );

            pInitArguments[1] <<= NamedValue(
                                    u"DenyList"_ustr,
                                    Any( rDenyList )
                                );


            if (xWindow.is())
                pInitArguments[2] <<= NamedValue(u"ParentWindow"_ustr, Any(xWindow));
        }

        try
        {
            xInit->initialize( aInitArguments );
        }
        catchconst Exception& )
        {
            OSL_FAIL( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
        }
    }


    // set multiselection mode
    if ( nFlags & FileDialogFlags::MultiSelection )
        mxFileDlg->setMultiSelectionMode( true );

    if ( nFlags & FileDialogFlags::Graphic ) // generate graphic filter only on demand
    {
        addGraphicFilter();
    }

    // Export dialog
    if ( mbExport )
    {
        mxFileDlg->setTitle( SfxResId( STR_SFX_EXPLORERFILE_EXPORT ) );
        try {
                css::uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY_THROW );
                xCtrlAccess->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR, true );
        }
        catchconst Exception & ) { }
    }

    // Save a copy dialog
    if ( nFlags & FileDialogFlags::SaveACopy )
    {
        mxFileDlg->setTitle( SfxResId( STR_PB_SAVEACOPY ) );
    }

    // the "insert file" dialog needs another title
    if ( mbInsert )
    {
        if ( nFlags & FileDialogFlags::InsertCompare )
        {
            mxFileDlg->setTitle( SfxResId( STR_PB_COMPAREDOC ) );
        }
        else if ( nFlags & FileDialogFlags::InsertMerge )
        {
            mxFileDlg->setTitle( SfxResId( STR_PB_MERGEDOC ) );
        }
        else
        {
            mxFileDlg->setTitle( SfxResId( STR_SFX_EXPLORERFILE_INSERT ) );
        }
        uno::Reference < XFilePickerControlAccess > xExtDlg( mxFileDlg, UNO_QUERY );
        if ( xExtDlg.is() )
        {
            try
            {
                xExtDlg->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK,
                                   SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT ) );
            }
            catchconst IllegalArgumentException& ){}
        }
    }

    // add the event listener
    mxFileDlg->addFilePickerListener( this );
}

css::uno::Reference<css::ui::dialogs::XFolderPicker2> createFolderPicker(const css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Window* pPreferredParent)
{
    auto xRet = css::ui::dialogs::FolderPicker::create(rContext);

    // see FileDialogHelper_Impl::FileDialogHelper_Impl (above) for args to FilePicker
    // reuse the same arguments for FolderPicker
    if (pPreferredParent && lcl_isSystemFilePicker(xRet))
    {
        uno::Reference< XInitialization > xInit(xRet, UNO_QUERY);
        if (xInit.is())
        {
            Sequence<Any> aInitArguments{ Any(sal_Int32(0)), Any(pPreferredParent->GetXWindow()) };

            try
            {
                xInit->initialize(aInitArguments);
            }
            catch (const Exception&)
            {
                OSL_FAIL( "createFolderPicker: could not initialize the picker!" );
            }
        }
    }

    return xRet;
}

FileDialogHelper_Impl::~FileDialogHelper_Impl()
{
    mpGraphicFilter.reset();

    if ( mbDeleteMatcher )
        delete mpMatcher;

    maPreviewIdle.ClearInvokeHandler();

    ::comphelper::disposeComponent( mxFileDlg );
}

void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId )
{
    DBG_ASSERT( _pControlId && _pHelpId, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
    if ( !_pControlId || !_pHelpId )
        return;

    // forward these ids to the file picker
    try
    {
        const OUString sHelpIdPrefix( INET_HID_SCHEME  );
        // the ids for the single controls
        uno::Reference< XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY );
        if ( xControlAccess.is() )
        {
            while ( *_pControlId )
            {
                DBG_ASSERT( INetURLObject( OStringToOUString( *_pHelpId, RTL_TEXTENCODING_UTF8 ) ).GetProtocol() == INetProtocol::NotValid, "Wrong HelpId!" );
                OUString sId = sHelpIdPrefix +
                    OUString( *_pHelpId, strlen( *_pHelpId ), RTL_TEXTENCODING_UTF8 );
                xControlAccess->setValue( *_pControlId, ControlActions::SET_HELP_URL, Any( sId ) );

                ++_pControlId; ++_pHelpId;
            }
        }
    }
    catchconst Exception& )
    {
        TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
    }
}

void FileDialogHelper_Impl::preExecute()
{
    loadConfig( );
    setDefaultValues( );
    updatePreviewState( false );

    implInitializeFileName( );

    enablePasswordBox( true );
    enableGpgEncrBox( true );
    updateFilterOptionsBox( );
    updateSelectionBox( );
    updateSignByDefault();
}

void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult )
{
    if ( ExecutableDialogResults::CANCEL != _nResult )
        saveConfig();
}

void FileDialogHelper_Impl::implInitializeFileName( )
{
    if ( maFileName.isEmpty() )
        return;

    INetURLObject aObj( maPath );
    aObj.Append( maFileName );

    // in case we're operating as save dialog, and "auto extension" is checked,
    // cut the extension from the name
    if ( !(mbIsSaveDlg && mbHasAutoExt) )
        return;

    try
    {
        bool bAutoExtChecked = false;

        uno::Reference < XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY );
        if  (   xControlAccess.is()
            &&  (   xControlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 )
                >>= bAutoExtChecked
                )
            )
        {
            if ( bAutoExtChecked )
            {   // cut the extension
                aObj.removeExtension( );
                mxFileDlg->setDefaultName(
                    aObj.GetLastName(INetURLObject::DecodeMechanism::WithCharset));
            }
        }
    }
    catchconst Exception& )
    {
        OSL_FAIL( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
    }
}

sal_Int16 FileDialogHelper_Impl::implDoExecute()
{
    preExecute();

    sal_Int16 nRet = ExecutableDialogResults::CANCEL;

//On MacOSX the native file picker has to run in the primordial thread because of drawing issues
//On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
//primordial thread as the ucb gnome-vfs2 provider was initialized in.

    {
        try
        {
#ifdef _WIN32
            if ( mbSystemPicker )
            {
                SolarMutexReleaser aSolarMutex;
                nRet = mxFileDlg->execute();
            }
            else
#endif
                nRet = mxFileDlg->execute();
        }
        catchconst Exception& )
        {
            TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::implDoExecute" );
        }
    }

    postExecute( nRet );

    return nRet;
}

void FileDialogHelper_Impl::implStartExecute()
{
    DBG_ASSERT( mxFileDlg.is(), "invalid file dialog" );

    assert(mbAsyncPicker);
    preExecute();

    try
    {
        uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( mxFileDlg, UNO_QUERY );
        if ( xAsyncDlg.is() )
            xAsyncDlg->startExecuteModal( this );
    }
    catchconst Exception& )
    {
        TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::implDoExecute" );
    }
}

ErrCode FileDialogHelper_Impl::execute( css::uno::Sequence<OUString>& rpURLList,
                                        std::optional<SfxAllItemSet>& rpSet,
                                        OUString&       rFilter,
                                        SignatureState const nScriptingSignatureState)
{
    // rFilter is a pure output parameter, it shouldn't be used for anything else
    // changing this would surely break code
    // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog

    // retrieves parameters from rpSet
    // for now only Password is used
    if ( rpSet )
    {
        // check password checkbox if the document had password before
        if( mbHasPassword )
        {
            const SfxBoolItem* pPassItem = rpSet->GetItem(SID_PASSWORDINTERACTION, false);
            // TODO: tdf#158839 problem: Is also true if the file is GPG encrypted. (not with a password)
            mbPwdCheckBoxState = ( pPassItem != nullptr && pPassItem->GetValue() );

            // in case the document has password to modify, the dialog should be shown
            const SfxUnoAnyItem* pPassToModifyItem = rpSet->GetItem(SID_MODIFYPASSWORDINFO, false);
            mbPwdCheckBoxState |= ( pPassToModifyItem && pPassToModifyItem->GetValue().hasValue() );
        }

        const SfxBoolItem* pSelectItem = rpSet->GetItem(SID_SELECTION, false);
        if ( pSelectItem )
            mbSelection = pSelectItem->GetValue();
        else
            mbSelectionEnabled = false;

        // the password will be set in case user decide so
        rpSet->ClearItem( SID_PASSWORDINTERACTION );
        if (rpSet->HasItem( SID_PASSWORD ))
        {
            // As the SID_ENCRYPTIONDATA and SID_PASSWORD are using for setting password together, we need to clear them both.
            // Note: Do not remove SID_ENCRYPTIONDATA without SID_PASSWORD
            rpSet->ClearItem( SID_PASSWORD );
            rpSet->ClearItem( SID_ENCRYPTIONDATA );
        }
        rpSet->ClearItem( SID_RECOMMENDREADONLY );
        rpSet->ClearItem( SID_MODIFYPASSWORDINFO );

    }

    if ( mbHasPassword && !mbPwdCheckBoxState )
    {
        mbPwdCheckBoxState = (
            SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::DocWarnRecommendPassword ) );
    }

    rpURLList = {};

    if ( ! mxFileDlg.is() )
        return ERRCODE_ABORT;

    if (ExecutableDialogResults::CANCEL == implDoExecute())
        return ERRCODE_ABORT;

    // fill the rpURLList
    rpURLList = mxFileDlg->getSelectedFiles();
    if (!rpURLList.hasElements())
        return ERRCODE_ABORT;

    uno::Reference<XFilePickerControlAccess> xCtrlAccess(mxFileDlg, UNO_QUERY);

    // create an itemset if there is no
    if( !rpSet )
        rpSet.emplace( SfxGetpApp()->GetPool() );

    // the item should remain only if it was set by the dialog
    rpSet->ClearItem( SID_SELECTION );

    if (mbExport && mbHasSelectionBox && xCtrlAccess)
    {
        try
        {
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 );
            bool bSelection = false;
            if ( aValue >>= bSelection )
                rpSet->Put( SfxBoolItem( SID_SELECTION, bSelection ) );
        }
        catchconst IllegalArgumentException& )
        {
            TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
        }
    }


    // set the read-only flag. When inserting a file, this flag is always set
    if ( mbInsert )
        rpSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
    else if ( ( FILEOPEN_READONLY_VERSION == m_nDialogType ) && xCtrlAccess.is() )
    {
        try
        {
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 );
            bool bReadOnly = false;
            if ( ( aValue >>= bReadOnly ) && bReadOnly )
                rpSet->Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) );
        }
        catchconst IllegalArgumentException& )
        {
            TOOLS_WARN_EXCEPTION( "sfx.dialog""FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
        }
    }
    if ( mbHasVersions && xCtrlAccess.is() )
    {
        try
        {
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
                                                ControlActions::GET_SELECTED_ITEM_INDEX );
            sal_Int32 nVersion = 0;
            if ( ( aValue >>= nVersion ) && nVersion > 0 )
                // open a special version; 0 == current version
                rpSet->Put( SfxInt16Item( SID_VERSION, static_cast<short>(nVersion) ) );
        }
        catchconst IllegalArgumentException& ){}
    }

    // set the filter
    getRealFilter( rFilter );

    std::shared_ptr<const SfxFilter> pCurrentFilter = getCurrentSfxFilter();

    // check, whether or not we have to display a password box
    if ( pCurrentFilter && mbHasPassword && mbIsPwdEnabled && xCtrlAccess.is() )
    {
        try
        {
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
            bool bPassWord = false;
            if ( ( aValue >>= bPassWord ) && bPassWord )
            {
                SvtSaveOptions::ODFSaneDefaultVersion nVersion{
                    SvtSaveOptions::ODFSVER_LATEST_EXTENDED};
                if (!comphelper::IsFuzzing())
                {
                    nVersion = GetODFSaneDefaultVersion();
                }
                // old per-zip-entry ODF encryption destroys macro signatures
                if (!::sfx2::UseODFWholesomeEncryption(nVersion)
                    && (   SignatureState::OK == nScriptingSignatureState
                        || SignatureState::INVALID == nScriptingSignatureState
                        || SignatureState::NOTVALIDATED == nScriptingSignatureState
                        || SignatureState::PARTIAL_OK == nScriptingSignatureState))
                {
                    std::unique_ptr<weld::MessageDialog> xBox(
                        Application::CreateMessageDialog(mpFrameWeld,
                            VclMessageType::Question, VclButtonsType::YesNo,
                            SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSCRIPTINGSIGNATURE)));
                    if (xBox->run() == RET_NO)
                    {
                        bPassWord = false;
                    }
                }
            }

            if (bPassWord)
            {
                // ask for a password
                const OUString& aDocName(rpURLList[0]);
                // TODO: tdf#158839 problem: Also asks for a password if CHECKBOX_GPGENCRYPTION && CHECKBOX_PASSWORD
                //       are checked. But only encrypts using GPG and discards the password.
                ErrCode errCode = RequestPassword(pCurrentFilter, aDocName, &*rpSet, GetFrameInterface());
                if (errCode != ERRCODE_NONE)
                    return errCode;
            }
        }
        catchconst IllegalArgumentException& ){}
    }
    // check, whether or not we have to display a key selection box
    if ( pCurrentFilter && mbHasPassword && xCtrlAccess.is() )
    {
        try
        {
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0 );
            bool bGpg = false;
            if ( ( aValue >>= bGpg ) && bGpg )
            {
                uno::Sequence< beans::NamedValue > aEncryptionData;
                while(true)
                {
                    try
                    {
                        // ask for keys
                        aEncryptionData
                            = ::comphelper::OStorageHelper::CreateGpgPackageEncryptionData(
                                GetFrameInterface());
                        break// user cancelled or we've some keys now
                    }
                    catchconst IllegalArgumentException& )
                    {
                        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(mpFrameWeld,
                                                                                 VclMessageType::Warning, VclButtonsType::Ok,
                                                                                 SfxResId(RID_SVXSTR_GPG_ENCRYPT_FAILURE)));
                        xBox->run();
                    }
                }

                if ( aEncryptionData.hasElements() )
                    rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::Any( aEncryptionData) ) );
                else
                    return ERRCODE_ABORT;
            }
        }
        catchconst IllegalArgumentException& ){}
    }
    if ( pCurrentFilter && xCtrlAccess.is() )
    {
        try
        {
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN, 0 );
            bool bSign = false;
            if ((aValue >>= bSign) && bSign)
            {
                rpSet->Put(SfxBoolItem(SID_GPGSIGN, bSign));
            }
        }
        catchconst IllegalArgumentException& ){}
    }

    SaveLastUsedFilter();
    return ERRCODE_NONE;
}

ErrCode FileDialogHelper_Impl::execute()
{
    if ( ! mxFileDlg.is() )
        return ERRCODE_ABORT;

    sal_Int16 nRet = implDoExecute();

    maPath = mxFileDlg->getDisplayDirectory();

    if ( ExecutableDialogResults::CANCEL == nRet )
        return ERRCODE_ABORT;
    else
    {
        return ERRCODE_NONE;
    }
}

OUString FileDialogHelper_Impl::getPath() const
{
    OUString aPath;

    if ( mxFileDlg.is() )
        aPath = mxFileDlg->getDisplayDirectory();

    if ( aPath.isEmpty() )
        aPath = maPath;

    return aPath;
}

OUString FileDialogHelper_Impl::getFilter() const
{
    OUString aFilter = getCurrentFilterUIName();

    if( aFilter.isEmpty() )
        aFilter = maCurFilter;

    return aFilter;
}

void FileDialogHelper_Impl::getRealFilter( OUString& _rFilter ) const
{
    _rFilter = getCurrentFilterUIName();

    if ( _rFilter.isEmpty() )
        _rFilter = maCurFilter;

    if ( !_rFilter.isEmpty() && mpMatcher )
    {
        std::shared_ptr<const SfxFilter> pFilter =
            mpMatcher->GetFilter4UIName( _rFilter, m_nMustFlags, m_nDontFlags );
        _rFilter = pFilter ? pFilter->GetFilterName() : OUString();
    }
}

void FileDialogHelper_Impl::verifyPath()
{
#ifdef UNX
    // lp#905355, fdo#43895
    // Check that the file has read only permission and is in /tmp -- this is
    //  the case if we have opened the file from the web with firefox only.
    if (maFileName.isEmpty()) {
        return;
    }
    INetURLObject url(maPath);
    if (url.GetProtocol() != INetProtocol::File
        || url.getName(0, true, INetURLObject::DecodeMechanism::WithCharset) != "tmp")
    {
        return;
    }
    if (maFileName.indexOf('/') != -1) {
        SAL_WARN("sfx.dialog", maFileName << " contains /");
        return;
    }
    url.insertName(
        maFileName, false, INetURLObject::LAST_SEGMENT,
        INetURLObject::EncodeMechanism::All);
    OUString sysPathU;
    osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL(
        url.GetMainURL(INetURLObject::DecodeMechanism::NONE), sysPathU);
    if (e != osl::FileBase::E_None) {
        SAL_WARN(
            "sfx.dialog",
            "getSystemPathFromFileURL("
                << url.GetMainURL(INetURLObject::DecodeMechanism::NONE) << ") failed with "
                << +e);
        return;
    }
    OString sysPathC;
    if (!sysPathU.convertToString(
            &sysPathC, osl_getThreadTextEncoding(),
            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
             | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
    {
        SAL_WARN(
            "sfx.dialog",
            "convertToString(" << sysPathU << ") failed for encoding "
                << +osl_getThreadTextEncoding());
        return;
    }
    struct stat aFileStat;
    if (stat(sysPathC.getStr(), &aFileStat) == -1) {
        SAL_WARN( "sfx.dialog""stat(" << sysPathC << ") failed with errno " << errno);
        return;
    }
    if ((aFileStat.st_mode & (S_IRWXO | S_IRWXG | S_IRWXU)) == S_IRUSR) {
        maPath = SvtPathOptions().GetWorkPath();
        mxFileDlg->setDisplayDirectory( maPath );
    }
#else
    (voidthis;
#endif
}

void FileDialogHelper_Impl::displayFolder( const OUString& _rPath )
{
    if ( _rPath.isEmpty() )
        // nothing to do
        return;

    maPath = _rPath;
    if ( mxFileDlg.is() )
    {
        try
        {
            mxFileDlg->setDisplayDirectory( maPath );
            verifyPath();
        }
        catchconst IllegalArgumentException& )
        {
            TOOLS_WARN_EXCEPTION( "sfx""FileDialogHelper_Impl::displayFolder" );
        }
    }
}

void FileDialogHelper_Impl::setFileName( const OUString& _rFile )
{
    maFileName = _rFile;
    if ( mxFileDlg.is() )
    {
        try
        {
            mxFileDlg->setDefaultName( maFileName );
            verifyPath();
        }
        catchconst IllegalArgumentException& )
        {
            TOOLS_WARN_EXCEPTION( "sfx""FileDialogHelper_Impl::setFileName" );
        }
    }
}

void FileDialogHelper_Impl::setFilter( const OUString& rFilter )
{
    DBG_ASSERT( rFilter.indexOf(':') == -1, "Old filter name used!");

    maCurFilter = rFilter;

    if ( !rFilter.isEmpty() && mpMatcher )
    {
        std::shared_ptr<const SfxFilter> pFilter = mpMatcher->GetFilter4FilterName(
                                        rFilter, m_nMustFlags, m_nDontFlags );
        if ( pFilter )
            maCurFilter = pFilter->GetUIName();
    }

    if ( !maCurFilter.isEmpty() && mxFileDlg.is() )
    {
        try
        {
            mxFileDlg->setCurrentFilter( maCurFilter );
        }
        catchconst IllegalArgumentException& ){}
    }
}

void FileDialogHelper_Impl::createMatcher( const OUString& rFactory )
{
    if (mbDeleteMatcher)
        delete mpMatcher;

    mpMatcher = new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) );
    mbDeleteMatcher = true;
}

void FileDialogHelper_Impl::addFilters( const OUString& rFactory,
                                        SfxFilterFlags nMust,
                                        SfxFilterFlags nDont )
{
    if ( ! mxFileDlg.is() )
        return;

    if (mbDeleteMatcher)
        delete mpMatcher;

    // we still need a matcher to convert UI names to filter names
    if ( rFactory.isEmpty() )
    {
        SfxApplication *pSfxApp = SfxGetpApp();
        mpMatcher = &pSfxApp->GetFilterMatcher();
        mbDeleteMatcher = false;
    }
    else
    {
        mpMatcher = new SfxFilterMatcher( rFactory );
        mbDeleteMatcher = true;
    }

    uno::Reference< XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
    uno::Reference< XContainerQuery > xFilterCont(
        xSMGR->createInstance(u"com.sun.star.document.FilterFactory"_ustr),
        UNO_QUERY);
    if ( ! xFilterCont.is() )
        return;

    m_nMustFlags |= nMust;
    m_nDontFlags |= nDont;

    // create the list of filters
    OUString sQuery =
        "getSortedFilterList()"
        ":module=" +
        rFactory + // use long name here !
        ":iflags=" +
        OUString::number(static_cast<sal_Int32>(m_nMustFlags)) +
        ":eflags=" +
        OUString::number(static_cast<sal_Int32>(m_nDontFlags));

    uno::Reference< XEnumeration > xResult;
    try
    {
        xResult = xFilterCont->createSubSetEnumerationByQuery(sQuery);
    }
    catchconst uno::Exception& )
    {
        SAL_WARN( "sfx.dialog""Could not get filters from the configuration!" );
    }

    TSortedFilterList         aIter   (xResult);

    // append the filters
    OUString sFirstFilter;
    if (OPEN == lcl_OpenOrSave(m_nDialogType))
        ::sfx2::appendFiltersForOpen( aIter, mxFileDlg, sFirstFilter, *this );
    else if ( mbExport )
        ::sfx2::appendExportFilters( aIter, mxFileDlg, sFirstFilter, *this );
    else
        ::sfx2::appendFiltersForSave( aIter, mxFileDlg, sFirstFilter, *this, rFactory );

    // set our initial selected filter (if we do not already have one)
    if ( maSelectFilter.isEmpty() )
        maSelectFilter = sFirstFilter;
}

void FileDialogHelper_Impl::addFilter( const OUString& rFilterName,
                                       const OUString& rExtension )
{
    if ( ! mxFileDlg.is() )
        return;

    try
    {
        mxFileDlg->appendFilter( rFilterName, rExtension );

        if ( maSelectFilter.isEmpty() )
            maSelectFilter = rFilterName;
    }
    catchconst IllegalArgumentException& )
    {
        SAL_WARN( "sfx.dialog""Could not append Filter" << rFilterName );
    }
}

void FileDialogHelper_Impl::addGraphicFilter()
{
    if ( ! mxFileDlg.is() )
        return;

    // create the list of filters
    mpGraphicFilter.reset( new GraphicFilter );
    sal_uInt16 i, j, nCount = mpGraphicFilter->GetImportFormatCount();

    // compute the extension string for all known import filters
    OUString aExtensions;

    for ( i = 0; i < nCount; i++ )
    {
        j = 0;
        whiletrue )
        {
            OUString sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ );
            if ( sWildcard.isEmpty() )
                break;
            if ( aExtensions.indexOf( sWildcard ) == -1 )
            {
                if ( !aExtensions.isEmpty() )
                    aExtensions += ";";
                aExtensions += sWildcard;
            }
        }
    }

#if defined(_WIN32)
    if ( aExtensions.getLength() > 240 )
        aExtensions = FILEDIALOG_FILTER_ALL;
#endif
    bool bIsInOpenMode = isInOpenMode();

    try
    {
        // if the extension is not "All files", insert "All images"
        if (aExtensions != FILEDIALOG_FILTER_ALL)
        {
            OUString aAllFilterName = SfxResId(STR_SFX_IMPORT_ALL_IMAGES);
            aAllFilterName = ::sfx2::addExtension( aAllFilterName, aExtensions, bIsInOpenMode, *this );
            mxFileDlg->appendFilter( aAllFilterName, aExtensions );
            maSelectFilter = aAllFilterName; // and make it the default
        }

        // rhbz#1715109 always include All files *.* or *
        OUString aAllFilesName = SfxResId( STR_SFX_FILTERNAME_ALL );
        aAllFilesName = ::sfx2::addExtension( aAllFilesName, FILEDIALOG_FILTER_ALL, bIsInOpenMode, *this );
        mxFileDlg->appendFilter( aAllFilesName, FILEDIALOG_FILTER_ALL );

        // if the extension is "All files", make that the default
        if (aExtensions == FILEDIALOG_FILTER_ALL)
            maSelectFilter = aAllFilesName;
    }
    catchconst IllegalArgumentException& )
    {
        SAL_WARN( "sfx.dialog""Could not append Filter" );
    }

    // Now add the filter
    for ( i = 0; i < nCount; i++ )
    {
        OUString aName = mpGraphicFilter->GetImportFormatName( i );
        OUString aExt;
        j = 0;
        whiletrue )
        {
            OUString sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ );
            if ( sWildcard.isEmpty() )
                break;
            if ( aExt.indexOf( sWildcard ) == -1 )
            {
                if ( !aExt.isEmpty() )
                    aExt += ";";
                aExt += sWildcard;
            }
        }
        aName = ::sfx2::addExtension( aName, aExt, bIsInOpenMode, *this );
        try
        {
            mxFileDlg->appendFilter( aName, aExt );
        }
        catchconst IllegalArgumentException& )
        {
            SAL_WARN( "sfx.dialog""Could not append Filter" );
        }
    }
}

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

--> maximum size reached

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

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.29 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.