Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/dialog/filedlghelper.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <memory>
21
#include <optional>
22
#include <string_view>
23
24
#include <sfx2/filedlghelper.hxx>
25
#include <sal/types.h>
26
#include <com/sun/star/lang/XInitialization.hpp>
27
#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
28
#include <com/sun/star/ui/dialogs/ControlActions.hpp>
29
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
30
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
31
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
32
#include <com/sun/star/ui/dialogs/FolderPicker.hpp>
33
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
34
#include <com/sun/star/ui/dialogs/XControlInformation.hpp>
35
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
36
#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
37
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
38
#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
39
#include <com/sun/star/lang/XServiceInfo.hpp>
40
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
41
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
42
#include <com/sun/star/beans/PropertyValue.hpp>
43
#include <com/sun/star/beans/NamedValue.hpp>
44
#include <com/sun/star/beans/XPropertySet.hpp>
45
#include <com/sun/star/embed/ElementModes.hpp>
46
#include <com/sun/star/container/XEnumeration.hpp>
47
#include <com/sun/star/container/XContainerQuery.hpp>
48
#include <com/sun/star/container/XNameAccess.hpp>
49
#include <com/sun/star/container/XNameContainer.hpp>
50
#include <com/sun/star/task/InteractionHandler.hpp>
51
#include <com/sun/star/task/PasswordRequestMode.hpp>
52
#include <com/sun/star/task/XInteractionRequest.hpp>
53
#include <com/sun/star/util/RevisionTag.hpp>
54
#include <comphelper/fileurl.hxx>
55
#include <comphelper/processfactory.hxx>
56
#include <comphelper/sequenceashashmap.hxx>
57
#include <comphelper/string.hxx>
58
#include <comphelper/types.hxx>
59
#include <tools/debug.hxx>
60
#include <tools/stream.hxx>
61
#include <tools/urlobj.hxx>
62
#include <vcl/bitmap.hxx>
63
#include <vcl/help.hxx>
64
#include <vcl/vclenum.hxx>
65
#include <vcl/weld/MessageDialog.hxx>
66
#include <unotools/ucbstreamhelper.hxx>
67
#include <unotools/ucbhelper.hxx>
68
#include <osl/file.hxx>
69
#include <osl/security.hxx>
70
#include <vcl/mnemonic.hxx>
71
#include <vcl/svapp.hxx>
72
#include <unotools/pathoptions.hxx>
73
#include <unotools/saveopt.hxx>
74
#include <unotools/securityoptions.hxx>
75
#include <svl/itemset.hxx>
76
#include <svl/eitem.hxx>
77
#include <svl/intitem.hxx>
78
#include <vcl/dibtools.hxx>
79
#include <vcl/graphicfilter.hxx>
80
#include <unotools/filteroptions_settings.hxx>
81
#include <unotools/viewoptions.hxx>
82
#include <svtools/helpids.h>
83
#include <comphelper/docpasswordrequest.hxx>
84
#include <comphelper/docpasswordhelper.hxx>
85
#include <ucbhelper/content.hxx>
86
#include <comphelper/storagehelper.hxx>
87
#include <sfx2/app.hxx>
88
#include <sfx2/frame.hxx>
89
#include <sfx2/docfile.hxx>
90
#include <sfx2/docfilt.hxx>
91
#include <sfx2/objsh.hxx>
92
#include <sfx2/sfxresid.hxx>
93
#include <sfx2/sfxsids.hrc>
94
#include <guisaveas.hxx>
95
#include "filtergrouping.hxx"
96
#include "filedlgimpl.hxx"
97
#include <fpicker/fpsofficeResMgr.hxx>
98
#include <fpicker/strings.hrc>
99
#include <sfx2/strings.hrc>
100
#include <sal/log.hxx>
101
#include <comphelper/sequence.hxx>
102
#include <comphelper/diagnose_ex.hxx>
103
#include <o3tl/string_view.hxx>
104
#include <officecfg/Office/Common.hxx>
105
106
#include <config_gpgme.h>
107
#if HAVE_FEATURE_GPGME
108
# include <com/sun/star/xml/crypto/SEInitializer.hpp>
109
# include <com/sun/star/xml/crypto/GPGSEInitializer.hpp>
110
# include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
111
#endif
112
#include <comphelper/xmlsechelper.hxx>
113
#include <unotools/useroptions.hxx>
114
115
#ifdef UNX
116
#include <errno.h>
117
#include <sys/stat.h>
118
#endif
119
120
using namespace ::com::sun::star;
121
using namespace ::com::sun::star::container;
122
using namespace ::com::sun::star::lang;
123
using namespace ::com::sun::star::ui::dialogs;
124
using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
125
using namespace ::com::sun::star::uno;
126
using namespace ::com::sun::star::beans;
127
using namespace ::cppu;
128
129
constexpr OUString IODLG_CONFIGNAME = u"FilePicker_Save"_ustr;
130
constexpr OUString IMPGRF_CONFIGNAME = u"FilePicker_Graph"_ustr;
131
constexpr OUString USERITEM_NAME = u"UserItem"_ustr;
132
133
namespace sfx2
134
{
135
136
namespace
137
{
138
    bool lclSupportsOOXMLEncryption(std::u16string_view aFilterName)
139
0
    {
140
0
        return  aFilterName == u"Calc MS Excel 2007 XML"
141
0
                ||  aFilterName == u"MS Word 2007 XML"
142
0
                ||  aFilterName == u"Impress MS PowerPoint 2007 XML"
143
0
                ||  aFilterName == u"Impress MS PowerPoint 2007 XML AutoPlay"
144
0
                ||  aFilterName == u"Calc Office Open XML"
145
0
                ||  aFilterName == u"Impress Office Open XML"
146
0
                ||  aFilterName == u"Impress Office Open XML AutoPlay"
147
0
                ||  aFilterName == u"Office Open XML Text";
148
0
    }
149
}
150
151
static std::optional<OUString> GetLastFilterConfigId( FileDialogHelper::Context _eContext )
152
0
{
153
0
    static constexpr OUStringLiteral aSD_EXPORT_IDENTIFIER(u"SdExportLastFilter");
154
0
    static constexpr OUStringLiteral aSI_EXPORT_IDENTIFIER(u"SiExportLastFilter");
155
0
    static constexpr OUStringLiteral aSW_EXPORT_IDENTIFIER(u"SwExportLastFilter");
156
157
0
    switch( _eContext )
158
0
    {
159
0
        case FileDialogHelper::DrawExport: return aSD_EXPORT_IDENTIFIER;
160
0
        case FileDialogHelper::ImpressExport: return aSI_EXPORT_IDENTIFIER;
161
0
        case FileDialogHelper::WriterExport: return aSW_EXPORT_IDENTIFIER;
162
0
        default: break;
163
0
    }
164
165
0
    return {};
166
0
}
167
168
static OUString EncodeSpaces_Impl( const OUString& rSource );
169
static OUString DecodeSpaces_Impl( const OUString& rSource );
170
171
// FileDialogHelper_Impl
172
173
// XFilePickerListener Methods
174
void SAL_CALL FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent& )
175
0
{
176
0
    SolarMutexGuard aGuard;
177
0
    mpAntiImpl->FileSelectionChanged();
178
0
}
179
180
void SAL_CALL FileDialogHelper_Impl::directoryChanged( const FilePickerEvent& )
181
0
{
182
0
    SolarMutexGuard aGuard;
183
0
    mpAntiImpl->DirectoryChanged();
184
0
}
185
186
OUString SAL_CALL FileDialogHelper_Impl::helpRequested( const FilePickerEvent& aEvent )
187
0
{
188
0
    SolarMutexGuard aGuard;
189
0
    return sfx2::FileDialogHelper::HelpRequested( aEvent );
190
0
}
191
192
void SAL_CALL FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent& aEvent )
193
0
{
194
0
    SolarMutexGuard aGuard;
195
0
    mpAntiImpl->ControlStateChanged( aEvent );
196
0
}
197
198
void SAL_CALL FileDialogHelper_Impl::dialogSizeChanged()
199
0
{
200
0
    SolarMutexGuard aGuard;
201
0
    mpAntiImpl->DialogSizeChanged();
202
0
}
203
204
// XDialogClosedListener Methods
205
void SAL_CALL FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent& _rEvent )
206
0
{
207
0
    SolarMutexGuard aGuard;
208
0
    mpAntiImpl->DialogClosed( _rEvent );
209
0
    postExecute( _rEvent.DialogResult );
210
0
}
211
212
// handle XFilePickerListener events
213
void FileDialogHelper_Impl::handleFileSelectionChanged()
214
0
{
215
0
    if ( mbHasVersions )
216
0
        updateVersions();
217
218
0
    if ( mbShowPreview )
219
0
        maPreviewIdle.Start();
220
0
}
221
222
void FileDialogHelper_Impl::handleDirectoryChanged()
223
0
{
224
0
    if ( mbShowPreview )
225
0
        TimeOutHdl_Impl( nullptr );
226
0
}
227
228
OUString FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent& aEvent )
229
0
{
230
0
    TranslateId aHelpId;
231
232
    // mapping from element id -> help id
233
0
    switch ( aEvent.ElementId )
234
0
    {
235
0
        case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
236
0
            aHelpId = STR_FILESAVE_AUTOEXTENSION;
237
0
            break;
238
239
0
        case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
240
0
            aHelpId = STR_FILESAVE_SAVEWITHPASSWORD;
241
0
            break;
242
243
0
        case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
244
0
            aHelpId = STR_FILESAVE_CUSTOMIZEFILTER;
245
0
            break;
246
247
0
        case ExtendedFilePickerElementIds::CHECKBOX_READONLY :
248
0
            aHelpId = STR_FILEOPEN_READONLY;
249
0
            break;
250
251
0
        case ExtendedFilePickerElementIds::CHECKBOX_LINK :
252
0
            aHelpId = STR_FILEDLG_LINK_CB;
253
0
            break;
254
255
0
        case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW :
256
0
            aHelpId = STR_FILEDLG_PREVIEW_CB;
257
0
            break;
258
259
0
        case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
260
0
            aHelpId = STR_FILESAVE_DOPLAY;
261
0
            break;
262
263
0
        case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL :
264
0
        case ExtendedFilePickerElementIds::LISTBOX_VERSION :
265
0
            aHelpId = STR_FILEOPEN_VERSION;
266
0
            break;
267
268
0
        case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL :
269
0
        case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
270
0
            aHelpId = STR_FILESAVE_TEMPLATE;
271
0
            break;
272
273
0
        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL :
274
0
        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
275
0
            aHelpId = STR_FILEOPEN_IMAGE_TEMPLATE;
276
0
            break;
277
278
0
        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR_LABEL :
279
0
        case ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR :
280
0
            aHelpId = STR_FILEOPEN_IMAGE_ANCHOR;
281
0
            break;
282
283
0
        case ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
284
0
            aHelpId = STR_FILESAVE_SELECTION;
285
0
            break;
286
287
0
        default:
288
0
            SAL_WARN( "sfx.dialog", "invalid element id" );
289
0
    }
290
291
0
    return aHelpId ? FpsResId(aHelpId) : OUString();
292
0
}
293
294
void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent& aEvent )
295
0
{
296
0
    switch ( aEvent.ElementId )
297
0
    {
298
0
        case CommonFilePickerElementIds::LISTBOX_FILTER:
299
0
            updateFilterOptionsBox();
300
0
            enablePasswordBox( false );
301
0
            enableGpgEncrBox( false );
302
0
            updateSelectionBox();
303
0
            updateSignByDefault();
304
            // only use it for export and with our own dialog
305
0
            if ( mbExport && !mbSystemPicker )
306
0
                updateExportButton();
307
0
            break;
308
309
0
        case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW:
310
0
            updatePreviewState(true);
311
0
            break;
312
0
    }
313
0
}
314
315
void FileDialogHelper_Impl::handleDialogSizeChanged()
316
0
{
317
0
    if ( mbShowPreview )
318
0
        TimeOutHdl_Impl( nullptr );
319
0
}
320
321
// XEventListener Methods
322
void SAL_CALL FileDialogHelper_Impl::disposing( const EventObject& )
323
0
{
324
0
    SolarMutexGuard aGuard;
325
0
    dispose();
326
0
}
327
328
void FileDialogHelper_Impl::dispose()
329
0
{
330
0
    if ( mxFileDlg.is() )
331
0
    {
332
        // remove the event listener
333
0
        mxFileDlg->removeFilePickerListener( this );
334
335
0
        ::comphelper::disposeComponent( mxFileDlg );
336
0
        mxFileDlg.clear();
337
0
    }
338
0
}
339
340
OUString FileDialogHelper_Impl::getCurrentFilterUIName() const
341
0
{
342
0
    OUString aFilterName;
343
344
0
    if( mxFileDlg.is() )
345
0
    {
346
0
        aFilterName = mxFileDlg->getCurrentFilter();
347
348
0
        if ( !aFilterName.isEmpty() && isShowFilterExtensionEnabled() )
349
0
            aFilterName = getFilterName( aFilterName );
350
0
    }
351
352
0
    return aFilterName;
353
0
}
354
355
void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString& _rContextIdentifier )
356
0
{
357
0
    SvtViewOptions aDlgOpt( EViewType::Dialog, IODLG_CONFIGNAME );
358
359
0
    if( aDlgOpt.Exists() )
360
0
    {
361
0
        OUString    aLastFilter;
362
0
        if( aDlgOpt.GetUserItem( _rContextIdentifier ) >>= aLastFilter )
363
0
            setFilter( aLastFilter );
364
0
    }
365
0
}
366
367
void FileDialogHelper_Impl::SaveLastUsedFilter()
368
0
{
369
0
    std::optional<OUString> pConfigId = GetLastFilterConfigId( meContext );
370
0
    if( pConfigId )
371
0
        SvtViewOptions( EViewType::Dialog, IODLG_CONFIGNAME ).SetUserItem( *pConfigId,
372
0
                            Any( getFilterWithExtension( getFilter() ) ) );
373
0
}
374
375
std::shared_ptr<const SfxFilter> FileDialogHelper_Impl::getCurrentSfxFilter()
376
0
{
377
0
    OUString aFilterName = getCurrentFilterUIName();
378
379
0
    if ( mpMatcher && !aFilterName.isEmpty() )
380
0
        return mpMatcher->GetFilter4UIName( aFilterName, m_nMustFlags, m_nDontFlags );
381
382
0
    return nullptr;
383
0
}
384
385
bool FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId, bool _bEnable )
386
0
{
387
0
    bool bIsEnabled = false;
388
389
0
    uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
390
0
    if ( xCtrlAccess.is() )
391
0
    {
392
0
        try
393
0
        {
394
0
            xCtrlAccess->enableControl( _nExtendedControlId, _bEnable );
395
0
            bIsEnabled = _bEnable;
396
0
        }
397
0
        catch( const IllegalArgumentException& )
398
0
        {
399
0
            TOOLS_WARN_EXCEPTION( "sfx", "FileDialogHelper_Impl::updateExtendedControl" );
400
0
        }
401
0
    }
402
0
    return bIsEnabled;
403
0
}
404
405
bool FileDialogHelper_Impl::CheckFilterOptionsCapability( const std::shared_ptr<const SfxFilter>& _pFilter )
406
0
{
407
0
    bool bResult = false;
408
409
0
    if( mxFilterCFG.is() && _pFilter )
410
0
    {
411
0
        try
412
0
        {
413
0
            Sequence < PropertyValue > aProps;
414
0
            Any aAny = mxFilterCFG->getByName( _pFilter->GetName() );
415
0
            if ( aAny >>= aProps )
416
0
            {
417
0
                OUString aServiceName;
418
0
                for (const auto& rProp : aProps)
419
0
                {
420
0
                    if( rProp.Name == "UIComponent" )
421
0
                    {
422
0
                        rProp.Value >>= aServiceName;
423
0
                        if( !aServiceName.isEmpty() )
424
0
                            bResult = true;
425
0
                    }
426
0
                }
427
0
            }
428
0
        }
429
0
        catch( const Exception& )
430
0
        {
431
0
        }
432
0
    }
433
434
0
    return bResult;
435
0
}
436
437
bool FileDialogHelper_Impl::isInOpenMode() const
438
0
{
439
0
    bool bRet = false;
440
441
0
    switch ( m_nDialogType )
442
0
    {
443
0
        case FILEOPEN_SIMPLE:
444
0
        case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
445
0
        case FILEOPEN_PLAY:
446
0
        case FILEOPEN_LINK_PLAY:
447
0
        case FILEOPEN_READONLY_VERSION:
448
0
        case FILEOPEN_READONLY_VERSION_FILTEROPTIONS:
449
0
        case FILEOPEN_LINK_PREVIEW:
450
0
        case FILEOPEN_PREVIEW:
451
0
            bRet = true;
452
0
    }
453
454
0
    return bRet;
455
0
}
456
457
void FileDialogHelper_Impl::updateFilterOptionsBox()
458
0
{
459
0
    if ( !m_bHaveFilterOptions )
460
0
        return;
461
462
0
    bool bFilterOptionsEnabled = CheckFilterOptionsCapability(getCurrentSfxFilter());
463
464
0
    updateExtendedControl(ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS,
465
0
                          bFilterOptionsEnabled);
466
467
0
    if (isInOpenMode())
468
0
    {
469
0
        if (auto xCtrlAccess = mxFileDlg.query<XFilePickerControlAccess>())
470
0
        {
471
0
            OUString filter;
472
0
            getRealFilter(filter);
473
0
            bool bChecked = bFilterOptionsEnabled && utl::isShowFilterOptionsDialog(filter);
474
0
            xCtrlAccess->setValue(ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, 0,
475
0
                                  Any(bChecked));
476
0
        }
477
0
    }
478
0
}
479
480
void FileDialogHelper_Impl::updateExportButton()
481
0
{
482
0
    uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
483
0
    if ( !xCtrlAccess.is() )
484
0
        return;
485
486
0
    OUString sOldLabel( xCtrlAccess->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK ) );
487
488
    // initialize button label; we need the label with the mnemonic char
489
0
    if ( maButtonLabel.isEmpty() || maButtonLabel.indexOf( MNEMONIC_CHAR ) == -1 )
490
0
    {
491
        // cut the ellipses, if necessary
492
0
        sal_Int32 nIndex = sOldLabel.indexOf( "..." );
493
0
        if ( -1 == nIndex )
494
0
            nIndex = sOldLabel.getLength();
495
0
        maButtonLabel = sOldLabel.copy( 0, nIndex );
496
0
    }
497
498
0
    OUString sLabel = maButtonLabel;
499
    // filter with options -> append ellipses on export button label
500
0
    if ( CheckFilterOptionsCapability( getCurrentSfxFilter() ) )
501
0
        sLabel += "...";
502
503
0
    if ( sOldLabel != sLabel )
504
0
    {
505
0
        try
506
0
        {
507
0
            xCtrlAccess->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK, sLabel );
508
0
        }
509
0
        catch( const IllegalArgumentException& )
510
0
        {
511
0
            TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::updateExportButton" );
512
0
        }
513
0
    }
514
0
}
515
516
void FileDialogHelper_Impl::updateSelectionBox()
517
0
{
518
0
    if ( !mbHasSelectionBox )
519
0
        return;
520
521
    // Does the selection box exist?
522
0
    bool bSelectionBoxFound = false;
523
0
    uno::Reference< XControlInformation > xCtrlInfo( mxFileDlg, UNO_QUERY );
524
0
    if ( xCtrlInfo.is() )
525
0
    {
526
0
        Sequence< OUString > aCtrlList = xCtrlInfo->getSupportedControls();
527
0
        bSelectionBoxFound = comphelper::findValue(aCtrlList, "SelectionBox") != -1;
528
0
    }
529
530
0
    if ( bSelectionBoxFound )
531
0
    {
532
0
        std::shared_ptr<const SfxFilter> pFilter = getCurrentSfxFilter();
533
0
        mbSelectionFltrEnabled = updateExtendedControl(
534
0
            ExtendedFilePickerElementIds::CHECKBOX_SELECTION,
535
0
            ( mbSelectionEnabled && pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::SUPPORTSSELECTION ) ) );
536
0
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
537
0
        xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, Any( mbSelection ) );
538
0
    }
539
0
}
540
541
void FileDialogHelper_Impl::updateSignByDefault()
542
0
{
543
#if HAVE_FEATURE_GPGME
544
    if (!mbHasSignByDefault)
545
        return;
546
547
    OUString aSigningKey = SvtUserOptions{}.GetSigningKey();
548
    updateExtendedControl(ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN, !aSigningKey.isEmpty());
549
#endif
550
0
}
551
552
void FileDialogHelper_Impl::enablePasswordBox( bool bInit )
553
0
{
554
0
    if ( ! mbHasPassword )
555
0
        return;
556
557
    // in case of initialization assume previous state to be false
558
0
    bool bWasEnabled = !bInit && mbIsPwdEnabled;
559
560
0
    std::shared_ptr<const SfxFilter> pCurrentFilter = getCurrentSfxFilter();
561
0
    mbIsPwdEnabled = updateExtendedControl(
562
0
        ExtendedFilePickerElementIds::CHECKBOX_PASSWORD,
563
0
        pCurrentFilter && ( pCurrentFilter->GetFilterFlags() & SfxFilterFlags::ENCRYPTION )
564
0
    );
565
566
0
    if( !bWasEnabled && mbIsPwdEnabled )
567
0
    {
568
0
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
569
0
        if( mbPwdCheckBoxState )
570
0
            xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, Any( true ) );
571
0
    }
572
0
    else if( bWasEnabled && !mbIsPwdEnabled )
573
0
    {
574
        // remember user settings until checkbox is enabled
575
0
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
576
0
        Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
577
0
        bool bPassWord = false;
578
0
        mbPwdCheckBoxState = ( aValue >>= bPassWord ) && bPassWord;
579
0
        xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, Any( false ) );
580
0
    }
581
0
}
582
583
void FileDialogHelper_Impl::enableGpgEncrBox( bool bInit )
584
0
{
585
0
    if ( ! mbHasPassword )  // CHECKBOX_GPGENCRYPTION is visible if CHECKBOX_PASSWORD is visible
586
0
        return;
587
588
    // in case of initialization assume previous state to be false
589
0
    bool bWasEnabled = !bInit && mbIsGpgEncrEnabled;
590
591
0
    std::shared_ptr<const SfxFilter> pCurrentFilter = getCurrentSfxFilter();
592
0
    mbIsGpgEncrEnabled = updateExtendedControl(
593
0
        ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION,
594
0
        pCurrentFilter && ( pCurrentFilter->GetFilterFlags() & SfxFilterFlags::GPGENCRYPTION )
595
0
    );
596
597
0
    if( !bWasEnabled && mbIsGpgEncrEnabled )
598
0
    {
599
0
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
600
0
        if( mbGpgCheckBoxState )
601
0
            xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0, Any( true ) );
602
0
    }
603
0
    else if( bWasEnabled && !mbIsGpgEncrEnabled )
604
0
    {
605
        // remember user settings until checkbox is enabled
606
0
        uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
607
0
        Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0 );
608
0
        bool bGpgEncryption = false;
609
0
        mbGpgCheckBoxState = ( aValue >>= bGpgEncryption ) && bGpgEncryption;
610
0
        xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0, Any( false ) );
611
0
    }
612
0
}
613
614
void FileDialogHelper_Impl::updatePreviewState( bool _bUpdatePreviewWindow )
615
0
{
616
0
    if ( !mbHasPreview )
617
0
        return;
618
619
0
    uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY );
620
621
    // check, whether or not we have to display a preview
622
0
    if ( !xCtrlAccess.is() )
623
0
        return;
624
625
0
    try
626
0
    {
627
0
        Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 );
628
0
        bool bShowPreview = false;
629
630
0
        if ( aValue >>= bShowPreview )
631
0
        {
632
0
            mbShowPreview = bShowPreview;
633
634
            // setShowState has currently no effect for the
635
            // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
636
0
            uno::Reference< XFilePreview > xFilePreview( mxFileDlg, UNO_QUERY );
637
0
            if ( xFilePreview.is() )
638
0
                xFilePreview->setShowState( mbShowPreview );
639
640
0
            if ( _bUpdatePreviewWindow )
641
0
                TimeOutHdl_Impl( nullptr );
642
0
        }
643
0
    }
644
0
    catch( const Exception& )
645
0
    {
646
0
        TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::updatePreviewState" );
647
0
    }
648
0
}
649
650
void FileDialogHelper_Impl::updateVersions()
651
0
{
652
0
    Sequence < OUString > aEntries;
653
0
    Sequence < OUString > aPathSeq = mxFileDlg->getSelectedFiles();
654
655
0
    if ( aPathSeq.getLength() == 1 )
656
0
    {
657
0
        INetURLObject aObj( aPathSeq[0] );
658
659
0
        if ( ( aObj.GetProtocol() == INetProtocol::File ) &&
660
0
            ( utl::UCBContentHelper::IsDocument( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) )
661
0
        {
662
0
            try
663
0
            {
664
0
                uno::Reference< embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
665
0
                                                                aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
666
0
                                                                embed::ElementModes::READ );
667
668
0
                DBG_ASSERT( xStorage.is(), "The method must return the storage or throw exception!" );
669
0
                if ( !xStorage.is() )
670
0
                    throw uno::RuntimeException();
671
672
0
                const uno::Sequence < util::RevisionTag > xVersions = SfxMedium::GetVersionList( xStorage );
673
674
0
                aEntries.realloc( xVersions.getLength() + 1 );
675
0
                aEntries.getArray()[0] = SfxResId( STR_SFX_FILEDLG_ACTUALVERSION );
676
677
0
                std::transform(xVersions.begin(), xVersions.end(), std::next(aEntries.getArray()),
678
0
                    [](const util::RevisionTag& rVersion) -> OUString { return rVersion.Identifier; });
679
0
            }
680
0
            catch( const uno::Exception& )
681
0
            {
682
0
            }
683
0
        }
684
0
    }
685
686
0
    uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
687
0
    Any aValue;
688
689
0
    try
690
0
    {
691
0
        xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
692
0
                        ControlActions::DELETE_ITEMS, aValue );
693
0
    }
694
0
    catch( const IllegalArgumentException& ){}
695
696
0
    if ( !aEntries.hasElements() )
697
0
        return;
698
699
0
    try
700
0
    {
701
0
        aValue <<= aEntries;
702
0
        xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
703
0
                        ControlActions::ADD_ITEMS, aValue );
704
705
0
        Any aPos;
706
0
        aPos <<= sal_Int32(0);
707
0
        xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
708
0
                        ControlActions::SET_SELECT_ITEM, aPos );
709
0
    }
710
0
    catch( const IllegalArgumentException& ){}
711
0
}
712
713
IMPL_LINK_NOARG(FileDialogHelper_Impl, TimeOutHdl_Impl, Timer *, void)
714
0
{
715
0
    if ( !mbHasPreview )
716
0
        return;
717
718
0
    maGraphic.Clear();
719
720
0
    Any aAny;
721
0
    uno::Reference < XFilePreview > xFilePicker( mxFileDlg, UNO_QUERY );
722
723
0
    if ( ! xFilePicker.is() )
724
0
        return;
725
726
0
    Sequence < OUString > aPathSeq = mxFileDlg->getSelectedFiles();
727
728
0
    if ( mbShowPreview && ( aPathSeq.getLength() == 1 ) )
729
0
    {
730
0
        const OUString&    aURL = aPathSeq[0];
731
732
0
        if ( ERRCODE_NONE == getGraphic( aURL, maGraphic ) )
733
0
        {
734
            // changed the code slightly;
735
            // before: the bitmap was scaled and
736
            // surrounded a white frame
737
            // now: the bitmap will only be scaled
738
            // and the filepicker implementation
739
            // is responsible for placing it at its
740
            // proper position and painting a frame
741
742
0
            Bitmap aBmp = maGraphic.GetBitmap();
743
0
            if ( !aBmp.IsEmpty() )
744
0
            {
745
                // scale the bitmap to the correct size
746
0
                sal_Int32 nOutWidth  = xFilePicker->getAvailableWidth();
747
0
                sal_Int32 nOutHeight = xFilePicker->getAvailableHeight();
748
0
                sal_Int32 nBmpWidth  = aBmp.GetSizePixel().Width();
749
0
                sal_Int32 nBmpHeight = aBmp.GetSizePixel().Height();
750
751
0
                double nXRatio = static_cast<double>(nOutWidth) / nBmpWidth;
752
0
                double nYRatio = static_cast<double>(nOutHeight) / nBmpHeight;
753
754
0
                if ( nXRatio < nYRatio )
755
0
                    aBmp.Scale( nXRatio, nXRatio );
756
0
                else
757
0
                    aBmp.Scale( nYRatio, nYRatio );
758
759
                // Convert to true color, to allow CopyPixel
760
0
                aBmp.Convert( BmpConversion::N24Bit );
761
762
                // and copy it into the Any
763
0
                SvMemoryStream aData;
764
765
0
                WriteDIB(aBmp, aData, false);
766
767
0
                const Sequence < sal_Int8 > aBuffer(
768
0
                    static_cast< const sal_Int8* >(aData.GetData()),
769
0
                    aData.GetEndOfData() );
770
771
0
                aAny <<= aBuffer;
772
0
            }
773
0
        }
774
0
    }
775
776
0
    try
777
0
    {
778
0
        SolarMutexReleaser aReleaseForCallback;
779
        // clear the preview window
780
0
        xFilePicker->setImage( FilePreviewImageFormats::BITMAP, aAny );
781
0
    }
782
0
    catch( const IllegalArgumentException& )
783
0
    {
784
0
    }
785
0
}
786
787
ErrCode FileDialogHelper_Impl::getGraphic( const OUString& rURL,
788
                                           Graphic& rGraphic )
789
0
{
790
0
    if ( utl::UCBContentHelper::IsFolder( rURL ) )
791
0
        return ERRCODE_IO_NOTAFILE;
792
793
0
    if ( !mpGraphicFilter )
794
0
        return ERRCODE_IO_NOTSUPPORTED;
795
796
    // select graphic filter from dialog filter selection
797
0
    OUString aCurFilter( getFilter() );
798
799
0
    sal_uInt16 nFilter = !aCurFilter.isEmpty() && mpGraphicFilter->GetImportFormatCount()
800
0
                    ? mpGraphicFilter->GetImportFormatNumber( aCurFilter )
801
0
                    : GRFILTER_FORMAT_DONTKNOW;
802
803
0
    INetURLObject aURLObj( rURL );
804
805
0
    if ( aURLObj.HasError() || INetProtocol::NotValid == aURLObj.GetProtocol() )
806
0
    {
807
0
        aURLObj.SetSmartProtocol( INetProtocol::File );
808
0
        aURLObj.SetSmartURL( rURL );
809
0
    }
810
811
0
    uno::Reference<task::XInteractionHandler2> xInteractionHandler =
812
0
        task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(),  GetFrameInterface());
813
814
0
    ErrCode nRet = ERRCODE_NONE;
815
816
0
    GraphicFilterImportFlags nFilterImportFlags = GraphicFilterImportFlags::SetLogsizeForJpeg;
817
    // non-local?
818
0
    if ( INetProtocol::File != aURLObj.GetProtocol() )
819
0
    {
820
0
        std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( rURL, StreamMode::READ );
821
822
0
        if( pStream )
823
0
            nRet = mpGraphicFilter->ImportGraphic(rGraphic, rURL, *pStream, nFilter, nullptr, nFilterImportFlags, -1, xInteractionHandler);
824
0
        else
825
0
            nRet = mpGraphicFilter->ImportGraphic(rGraphic, aURLObj, nFilter, nullptr, nFilterImportFlags, xInteractionHandler);
826
0
    }
827
0
    else
828
0
    {
829
0
        nRet = mpGraphicFilter->ImportGraphic(rGraphic, aURLObj, nFilter, nullptr, nFilterImportFlags, xInteractionHandler);
830
0
    }
831
832
0
    return nRet;
833
0
}
834
835
ErrCode FileDialogHelper_Impl::getGraphic( Graphic& rGraphic )
836
0
{
837
0
    ErrCode nRet = ERRCODE_NONE;
838
839
    // rhbz#1079672 do not return maGraphic, it needs not to be the selected file
840
841
0
    Sequence<OUString> aPathSeq = mxFileDlg->getSelectedFiles();
842
843
0
    if (aPathSeq.getLength() > 0)
844
0
    {
845
0
        for (const auto& fileName : aPathSeq)
846
0
        {
847
0
            nRet = getGraphic(fileName, rGraphic);
848
0
            if (nRet != ERRCODE_NONE)
849
0
                return nRet;
850
0
        }
851
0
    }
852
0
    else
853
0
        nRet = ERRCODE_IO_GENERAL;
854
855
0
    return nRet;
856
0
}
857
858
static bool lcl_isSystemFilePicker( const uno::Reference< XExecutableDialog >& _rxFP )
859
0
{
860
0
    try
861
0
    {
862
0
        uno::Reference< XServiceInfo > xSI( _rxFP, UNO_QUERY );
863
0
        if ( !xSI.is() )
864
0
            return true;
865
0
        return xSI->supportsService( u"com.sun.star.ui.dialogs.SystemFilePicker"_ustr );
866
0
    }
867
0
    catch( const Exception& )
868
0
    {
869
0
    }
870
0
    return false;
871
0
}
872
873
namespace {
874
875
bool lcl_isAsyncFilePicker( const uno::Reference< XExecutableDialog >& _rxFP )
876
0
{
877
0
    try
878
0
    {
879
0
        uno::Reference<XAsynchronousExecutableDialog> xSI(_rxFP, UNO_QUERY);
880
0
        return xSI.is();
881
0
    }
882
0
    catch( const Exception& )
883
0
    {
884
0
    }
885
0
    return false;
886
0
}
887
888
enum class open_or_save_t {OPEN, SAVE, UNDEFINED};
889
890
}
891
892
static open_or_save_t lcl_OpenOrSave(sal_Int16 const nDialogType)
893
0
{
894
0
    switch (nDialogType)
895
0
    {
896
0
        case FILEOPEN_SIMPLE:
897
0
        case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
898
0
        case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR:
899
0
        case FILEOPEN_PLAY:
900
0
        case FILEOPEN_LINK_PLAY:
901
0
        case FILEOPEN_READONLY_VERSION:
902
0
        case FILEOPEN_READONLY_VERSION_FILTEROPTIONS:
903
0
        case FILEOPEN_LINK_PREVIEW:
904
0
        case FILEOPEN_PREVIEW:
905
0
            return open_or_save_t::OPEN;
906
0
        case FILESAVE_SIMPLE:
907
0
        case FILESAVE_AUTOEXTENSION_PASSWORD:
908
0
        case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
909
0
        case FILESAVE_AUTOEXTENSION_SELECTION:
910
0
        case FILESAVE_AUTOEXTENSION_TEMPLATE:
911
0
        case FILESAVE_AUTOEXTENSION:
912
0
            return open_or_save_t::SAVE;
913
0
        default:
914
0
            assert(false); // invalid dialog type
915
0
    }
916
0
    return open_or_save_t::UNDEFINED;
917
0
}
918
919
// FileDialogHelper_Impl
920
921
css::uno::Reference<css::awt::XWindow> FileDialogHelper_Impl::GetFrameInterface()
922
0
{
923
0
    if (mpFrameWeld)
924
0
        return mpFrameWeld->GetXWindow();
925
0
    return css::uno::Reference<css::awt::XWindow>();
926
0
}
927
928
FileDialogHelper_Impl::FileDialogHelper_Impl(
929
    FileDialogHelper* _pAntiImpl,
930
    sal_Int16 nDialogType,
931
    FileDialogFlags nFlags,
932
    sal_Int16 nDialog,
933
    weld::Window* pFrameWeld,
934
    const OUString& sPreselectedDir,
935
    const css::uno::Sequence< OUString >& rDenyList
936
    )
937
0
    :msPreselectedDir( sPreselectedDir )
938
0
    ,maPreviewIdle("sfx2 FileDialogHelper_Impl maPreviewIdle")
939
0
    ,m_nDialogType          ( nDialogType )
940
0
    ,meContext              ( FileDialogHelper::UnknownContext )
941
0
{
942
0
    const char* pServiceName=nullptr;
943
0
    switch (nDialog)
944
0
    {
945
0
        case SFX2_IMPL_DIALOG_SYSTEM:
946
0
        case SFX2_IMPL_DIALOG_OOO:
947
0
            pServiceName = "com.sun.star.ui.dialogs.OfficeFilePicker";
948
0
            break;
949
0
        case SFX2_IMPL_DIALOG_REMOTE:
950
0
            pServiceName = "com.sun.star.ui.dialogs.RemoteFilePicker";
951
0
            break;
952
0
        default:
953
0
            pServiceName = "com.sun.star.ui.dialogs.FilePicker";
954
0
            break;
955
0
    }
956
957
0
    OUString aService = OUString::createFromAscii( pServiceName );
958
959
0
    uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
960
961
    // create the file open dialog
962
    // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION
963
964
0
    mpFrameWeld             = pFrameWeld;
965
0
    mpAntiImpl              = _pAntiImpl;
966
0
    mbHasAutoExt            = false;
967
0
    mbHasPassword           = false;
968
0
    mbHasSignByDefault      = false;
969
0
    m_bHaveFilterOptions    = false;
970
0
    mbIsPwdEnabled          = true;
971
0
    mbIsGpgEncrEnabled      = true;
972
0
    mbHasVersions           = false;
973
0
    mbHasPreview            = false;
974
0
    mbShowPreview           = false;
975
0
    mbDeleteMatcher         = false;
976
0
    mbInsert                = bool(nFlags & (FileDialogFlags::Insert|
977
0
                                             FileDialogFlags::InsertCompare|
978
0
                                             FileDialogFlags::InsertMerge));
979
0
    mbExport                = bool(nFlags & FileDialogFlags::Export);
980
0
    mbIsSaveDlg             = false;
981
0
    mbPwdCheckBoxState      = false;
982
0
    mbGpgCheckBoxState      = false;
983
0
    mbSelection             = false;
984
0
    mbSelectionEnabled      = true;
985
0
    mbHasSelectionBox       = false;
986
0
    mbSelectionFltrEnabled  = false;
987
988
    // default settings
989
0
    m_nDontFlags = SFX_FILTER_NOTINSTALLED | SfxFilterFlags::INTERNAL | SfxFilterFlags::NOTINFILEDLG;
990
0
    if (open_or_save_t::OPEN == lcl_OpenOrSave(m_nDialogType))
991
0
        m_nMustFlags = SfxFilterFlags::IMPORT;
992
0
    else
993
0
        m_nMustFlags = SfxFilterFlags::EXPORT;
994
995
996
0
    mpMatcher = nullptr;
997
0
    mpGraphicFilter = nullptr;
998
999
    // create the picker component
1000
0
    mxFileDlg.set(xFactory->createInstance( aService ), css::uno::UNO_QUERY);
1001
0
    mbSystemPicker = lcl_isSystemFilePicker( mxFileDlg );
1002
0
    mbAsyncPicker = lcl_isAsyncFilePicker(mxFileDlg);
1003
1004
0
    if ( ! mxFileDlg.is() )
1005
0
    {
1006
0
        return;
1007
0
    }
1008
1009
0
    uno::Reference< XInitialization > xInit( mxFileDlg, UNO_QUERY );
1010
0
    if ( xInit.is() )
1011
0
    {
1012
0
        sal_Int16 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE;
1013
1014
0
        switch ( m_nDialogType )
1015
0
        {
1016
0
            case FILEOPEN_SIMPLE:
1017
0
                nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE;
1018
0
                break;
1019
1020
0
            case FILESAVE_SIMPLE:
1021
0
                nTemplateDescription = TemplateDescription::FILESAVE_SIMPLE;
1022
0
                mbIsSaveDlg = true;
1023
0
                break;
1024
1025
0
            case FILESAVE_AUTOEXTENSION_PASSWORD:
1026
0
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD;
1027
0
                mbHasPassword = true;
1028
0
                mbHasAutoExt = true;
1029
0
                mbIsSaveDlg = true;
1030
0
                mbHasSignByDefault = true;
1031
0
                break;
1032
1033
0
            case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
1034
0
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS;
1035
0
                mbHasPassword = true;
1036
1037
0
                m_bHaveFilterOptions = true;
1038
0
                if( xFactory.is() )
1039
0
                {
1040
0
                    mxFilterCFG.set(
1041
0
                        xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ),
1042
0
                        UNO_QUERY );
1043
0
                }
1044
1045
0
                mbHasAutoExt = true;
1046
0
                mbIsSaveDlg = true;
1047
0
                mbHasSignByDefault = true;
1048
0
                break;
1049
1050
0
            case FILESAVE_AUTOEXTENSION_SELECTION:
1051
0
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION;
1052
0
                mbHasAutoExt = true;
1053
0
                mbIsSaveDlg = true;
1054
0
                mbHasSelectionBox = true;
1055
0
                if ( mbExport && !mxFilterCFG.is() && xFactory.is() )
1056
0
                {
1057
0
                    mxFilterCFG.set(
1058
0
                        xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ),
1059
0
                        UNO_QUERY );
1060
0
                }
1061
0
                break;
1062
1063
0
            case FILESAVE_AUTOEXTENSION_TEMPLATE:
1064
0
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE;
1065
0
                mbHasAutoExt = true;
1066
0
                mbIsSaveDlg = true;
1067
0
                break;
1068
1069
0
            case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
1070
0
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE;
1071
0
                mbHasPreview = true;
1072
0
                break;
1073
1074
0
            case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR:
1075
0
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR;
1076
0
                mbHasPreview = true;
1077
0
                break;
1078
1079
0
            case FILEOPEN_PLAY:
1080
0
                nTemplateDescription = TemplateDescription::FILEOPEN_PLAY;
1081
0
                break;
1082
1083
0
            case FILEOPEN_LINK_PLAY:
1084
0
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PLAY;
1085
0
                break;
1086
1087
0
            case FILEOPEN_READONLY_VERSION:
1088
0
                nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION;
1089
0
                mbHasVersions = true;
1090
0
                break;
1091
1092
0
            case FILEOPEN_READONLY_VERSION_FILTEROPTIONS:
1093
0
                nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION_FILTEROPTIONS;
1094
0
                m_bHaveFilterOptions = true;
1095
0
                if( xFactory.is() )
1096
0
                {
1097
0
                    mxFilterCFG.set(
1098
0
                        xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ),
1099
0
                        UNO_QUERY );
1100
0
                }
1101
0
                mbHasVersions = true;
1102
0
                break;
1103
1104
0
            case FILEOPEN_LINK_PREVIEW:
1105
0
                nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW;
1106
0
                mbHasPreview = true;
1107
0
                break;
1108
1109
0
            case FILESAVE_AUTOEXTENSION:
1110
0
                nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION;
1111
0
                mbHasAutoExt = true;
1112
0
                mbIsSaveDlg = true;
1113
0
                break;
1114
1115
0
            case FILEOPEN_PREVIEW:
1116
0
                nTemplateDescription = TemplateDescription::FILEOPEN_PREVIEW;
1117
0
                mbHasPreview = true;
1118
0
                break;
1119
1120
0
            default:
1121
0
                SAL_WARN( "sfx.dialog", "FileDialogHelper::ctor with unknown type" );
1122
0
                break;
1123
0
        }
1124
1125
0
        if (mbHasPreview)
1126
0
        {
1127
0
            maPreviewIdle.SetPriority( TaskPriority::LOWEST );
1128
0
            maPreviewIdle.SetInvokeHandler( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) );
1129
0
        }
1130
1131
0
        auto xWindow = GetFrameInterface();
1132
1133
0
        Sequence < Any > aInitArguments(!xWindow.is() ? 2 : 3);
1134
0
        auto pInitArguments = aInitArguments.getArray();
1135
1136
        // This is a hack. We currently know that the internal file picker implementation
1137
        // supports the extended arguments as specified below.
1138
        // TODO:
1139
        // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
1140
        // b) adjust the implementation of the system file picker to that it recognizes it
1141
0
        if ( mbSystemPicker )
1142
0
        {
1143
0
            pInitArguments[0] <<= nTemplateDescription;
1144
0
            if (xWindow.is())
1145
0
                pInitArguments[1] <<= xWindow;
1146
0
        }
1147
0
        else
1148
0
        {
1149
0
            pInitArguments[0] <<= NamedValue(
1150
0
                                    u"TemplateDescription"_ustr,
1151
0
                                    Any( nTemplateDescription )
1152
0
                                );
1153
1154
0
            pInitArguments[1] <<= NamedValue(
1155
0
                                    u"DenyList"_ustr,
1156
0
                                    Any( rDenyList )
1157
0
                                );
1158
1159
1160
0
            if (xWindow.is())
1161
0
                pInitArguments[2] <<= NamedValue(u"ParentWindow"_ustr, Any(xWindow));
1162
0
        }
1163
1164
0
        try
1165
0
        {
1166
0
            xInit->initialize( aInitArguments );
1167
0
        }
1168
0
        catch( const Exception& )
1169
0
        {
1170
0
            OSL_FAIL( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
1171
0
        }
1172
0
    }
1173
1174
1175
    // set multiselection mode
1176
0
    if ( nFlags & FileDialogFlags::MultiSelection )
1177
0
        mxFileDlg->setMultiSelectionMode( true );
1178
1179
0
    if ( nFlags & FileDialogFlags::Graphic ) // generate graphic filter only on demand
1180
0
    {
1181
0
        addGraphicFilter();
1182
0
    }
1183
1184
    // Export dialog
1185
0
    if ( mbExport )
1186
0
    {
1187
0
        mxFileDlg->setTitle( SfxResId( STR_SFX_EXPLORERFILE_EXPORT ) );
1188
0
        try {
1189
0
                css::uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY_THROW );
1190
0
                xCtrlAccess->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR, true );
1191
0
        }
1192
0
        catch( const Exception & ) { }
1193
0
    }
1194
1195
    // Save a copy dialog
1196
0
    if ( nFlags & FileDialogFlags::SaveACopy )
1197
0
    {
1198
0
        mxFileDlg->setTitle( SfxResId( STR_PB_SAVEACOPY ) );
1199
0
    }
1200
1201
    // the "insert file" dialog needs another title
1202
0
    if ( mbInsert )
1203
0
    {
1204
0
        if ( nFlags & FileDialogFlags::InsertCompare )
1205
0
        {
1206
0
            mxFileDlg->setTitle( SfxResId( STR_PB_COMPAREDOC ) );
1207
0
        }
1208
0
        else if ( nFlags & FileDialogFlags::InsertMerge )
1209
0
        {
1210
0
            mxFileDlg->setTitle( SfxResId( STR_PB_MERGEDOC ) );
1211
0
        }
1212
0
        else
1213
0
        {
1214
0
            mxFileDlg->setTitle( SfxResId( STR_SFX_EXPLORERFILE_INSERT ) );
1215
0
        }
1216
0
        uno::Reference < XFilePickerControlAccess > xExtDlg( mxFileDlg, UNO_QUERY );
1217
0
        if ( xExtDlg.is() )
1218
0
        {
1219
0
            try
1220
0
            {
1221
0
                xExtDlg->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK,
1222
0
                                   SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT ) );
1223
0
            }
1224
0
            catch( const IllegalArgumentException& ){}
1225
0
        }
1226
0
    }
1227
1228
    // add the event listener
1229
0
    mxFileDlg->addFilePickerListener( this );
1230
0
}
1231
1232
css::uno::Reference<css::ui::dialogs::XFolderPicker2> createFolderPicker(const css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Window* pPreferredParent)
1233
0
{
1234
0
    auto xRet = css::ui::dialogs::FolderPicker::create(rContext);
1235
1236
    // see FileDialogHelper_Impl::FileDialogHelper_Impl (above) for args to FilePicker
1237
    // reuse the same arguments for FolderPicker
1238
0
    if (pPreferredParent && lcl_isSystemFilePicker(xRet))
1239
0
    {
1240
0
        uno::Reference< XInitialization > xInit(xRet, UNO_QUERY);
1241
0
        if (xInit.is())
1242
0
        {
1243
0
            Sequence<Any> aInitArguments{ Any(sal_Int32(0)), Any(pPreferredParent->GetXWindow()) };
1244
1245
0
            try
1246
0
            {
1247
0
                xInit->initialize(aInitArguments);
1248
0
            }
1249
0
            catch (const Exception&)
1250
0
            {
1251
0
                OSL_FAIL( "createFolderPicker: could not initialize the picker!" );
1252
0
            }
1253
0
        }
1254
0
    }
1255
1256
0
    return xRet;
1257
0
}
1258
1259
FileDialogHelper_Impl::~FileDialogHelper_Impl()
1260
0
{
1261
0
    mpGraphicFilter.reset();
1262
1263
0
    if ( mbDeleteMatcher )
1264
0
        delete mpMatcher;
1265
1266
0
    maPreviewIdle.ClearInvokeHandler();
1267
1268
0
    ::comphelper::disposeComponent( mxFileDlg );
1269
0
}
1270
1271
void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId )
1272
0
{
1273
0
    DBG_ASSERT( _pControlId && _pHelpId, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
1274
0
    if ( !_pControlId || !_pHelpId )
1275
0
        return;
1276
1277
    // forward these ids to the file picker
1278
0
    try
1279
0
    {
1280
0
        const OUString sHelpIdPrefix( INET_HID_SCHEME  );
1281
        // the ids for the single controls
1282
0
        uno::Reference< XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY );
1283
0
        if ( xControlAccess.is() )
1284
0
        {
1285
0
            while ( *_pControlId )
1286
0
            {
1287
0
                DBG_ASSERT( INetURLObject( OStringToOUString( *_pHelpId, RTL_TEXTENCODING_UTF8 ) ).GetProtocol() == INetProtocol::NotValid, "Wrong HelpId!" );
1288
0
                OUString sId = sHelpIdPrefix +
1289
0
                    OUString( *_pHelpId, strlen( *_pHelpId ), RTL_TEXTENCODING_UTF8 );
1290
0
                xControlAccess->setValue( *_pControlId, ControlActions::SET_HELP_URL, Any( sId ) );
1291
1292
0
                ++_pControlId; ++_pHelpId;
1293
0
            }
1294
0
        }
1295
0
    }
1296
0
    catch( const Exception& )
1297
0
    {
1298
0
        TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
1299
0
    }
1300
0
}
1301
1302
void FileDialogHelper_Impl::preExecute()
1303
0
{
1304
0
    loadConfig( );
1305
0
    setDefaultValues( );
1306
0
    updatePreviewState( false );
1307
1308
0
    implInitializeFileName( );
1309
1310
0
    enablePasswordBox( true );
1311
0
    enableGpgEncrBox( true );
1312
0
    updateFilterOptionsBox( );
1313
0
    updateSelectionBox( );
1314
0
    updateSignByDefault();
1315
0
}
1316
1317
void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult )
1318
0
{
1319
0
    if ( ExecutableDialogResults::CANCEL != _nResult )
1320
0
        saveConfig();
1321
0
}
1322
1323
void FileDialogHelper_Impl::implInitializeFileName( )
1324
0
{
1325
0
    if ( maFileName.isEmpty() )
1326
0
        return;
1327
1328
0
    INetURLObject aObj( maPath );
1329
0
    aObj.Append( maFileName );
1330
1331
    // in case we're operating as save dialog, and "auto extension" is checked,
1332
    // cut the extension from the name
1333
0
    if ( !(mbIsSaveDlg && mbHasAutoExt) )
1334
0
        return;
1335
1336
0
    try
1337
0
    {
1338
0
        bool bAutoExtChecked = false;
1339
1340
0
        uno::Reference < XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY );
1341
0
        if  (   xControlAccess.is()
1342
0
            &&  (   xControlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 )
1343
0
                >>= bAutoExtChecked
1344
0
                )
1345
0
            )
1346
0
        {
1347
0
            if ( bAutoExtChecked )
1348
0
            {   // cut the extension
1349
0
                aObj.removeExtension( );
1350
0
                mxFileDlg->setDefaultName(
1351
0
                    aObj.GetLastName(INetURLObject::DecodeMechanism::WithCharset));
1352
0
            }
1353
0
        }
1354
0
    }
1355
0
    catch( const Exception& )
1356
0
    {
1357
0
        OSL_FAIL( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
1358
0
    }
1359
0
}
1360
1361
sal_Int16 FileDialogHelper_Impl::implDoExecute()
1362
0
{
1363
0
    preExecute();
1364
1365
0
    sal_Int16 nRet = ExecutableDialogResults::CANCEL;
1366
1367
//On MacOSX the native file picker has to run in the primordial thread because of drawing issues
1368
//On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
1369
//primordial thread as the ucb gnome-vfs2 provider was initialized in.
1370
1371
0
    {
1372
0
        try
1373
0
        {
1374
#ifdef _WIN32
1375
            if ( mbSystemPicker )
1376
            {
1377
                SolarMutexReleaser aSolarMutex;
1378
                nRet = mxFileDlg->execute();
1379
            }
1380
            else
1381
#endif
1382
0
                nRet = mxFileDlg->execute();
1383
0
        }
1384
0
        catch( const Exception& )
1385
0
        {
1386
0
            TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::implDoExecute" );
1387
0
        }
1388
0
    }
1389
1390
0
    postExecute( nRet );
1391
1392
0
    return nRet;
1393
0
}
1394
1395
void FileDialogHelper_Impl::implStartExecute()
1396
0
{
1397
0
    DBG_ASSERT( mxFileDlg.is(), "invalid file dialog" );
1398
1399
0
    assert(mbAsyncPicker);
1400
0
    preExecute();
1401
1402
0
    try
1403
0
    {
1404
0
        uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( mxFileDlg, UNO_QUERY );
1405
0
        if ( xAsyncDlg.is() )
1406
0
            xAsyncDlg->startExecuteModal( this );
1407
0
    }
1408
0
    catch( const Exception& )
1409
0
    {
1410
0
        TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::implDoExecute" );
1411
0
    }
1412
0
}
1413
1414
ErrCode FileDialogHelper_Impl::execute( css::uno::Sequence<OUString>& rpURLList,
1415
                                        std::optional<SfxAllItemSet>& rpSet,
1416
                                        OUString&       rFilter,
1417
                                        SignatureState const nScriptingSignatureState)
1418
0
{
1419
    // rFilter is a pure output parameter, it shouldn't be used for anything else
1420
    // changing this would surely break code
1421
    // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog
1422
1423
    // retrieves parameters from rpSet
1424
    // for now only Password is used
1425
0
    if ( rpSet )
1426
0
    {
1427
        // check password checkbox if the document had password before
1428
0
        if( mbHasPassword )
1429
0
        {
1430
0
            const SfxBoolItem* pPassItem = rpSet->GetItem(SID_PASSWORDINTERACTION, false);
1431
            // TODO: tdf#158839 problem: Is also true if the file is GPG encrypted. (not with a password)
1432
0
            mbPwdCheckBoxState = ( pPassItem != nullptr && pPassItem->GetValue() );
1433
1434
            // in case the document has password to modify, the dialog should be shown
1435
0
            const SfxUnoAnyItem* pPassToModifyItem = rpSet->GetItem(SID_MODIFYPASSWORDINFO, false);
1436
0
            mbPwdCheckBoxState |= ( pPassToModifyItem && pPassToModifyItem->GetValue().hasValue() );
1437
0
        }
1438
1439
0
        const SfxBoolItem* pSelectItem = rpSet->GetItem(SID_SELECTION, false);
1440
0
        if ( pSelectItem )
1441
0
            mbSelection = pSelectItem->GetValue();
1442
0
        else
1443
0
            mbSelectionEnabled = false;
1444
1445
        // the password will be set in case user decide so
1446
0
        rpSet->ClearItem( SID_PASSWORDINTERACTION );
1447
0
        if (rpSet->HasItem( SID_PASSWORD ))
1448
0
        {
1449
            // As the SID_ENCRYPTIONDATA and SID_PASSWORD are using for setting password together, we need to clear them both.
1450
            // Note: Do not remove SID_ENCRYPTIONDATA without SID_PASSWORD
1451
0
            rpSet->ClearItem( SID_PASSWORD );
1452
0
            rpSet->ClearItem( SID_ENCRYPTIONDATA );
1453
0
        }
1454
0
        rpSet->ClearItem( SID_RECOMMENDREADONLY );
1455
0
        rpSet->ClearItem( SID_MODIFYPASSWORDINFO );
1456
1457
0
    }
1458
1459
0
    if ( mbHasPassword && !mbPwdCheckBoxState )
1460
0
    {
1461
0
        mbPwdCheckBoxState = (
1462
0
            SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::DocWarnRecommendPassword ) );
1463
0
    }
1464
1465
0
    rpURLList = {};
1466
1467
0
    if ( ! mxFileDlg.is() )
1468
0
        return ERRCODE_ABORT;
1469
1470
0
    if (ExecutableDialogResults::CANCEL == implDoExecute())
1471
0
        return ERRCODE_ABORT;
1472
1473
    // fill the rpURLList
1474
0
    rpURLList = mxFileDlg->getSelectedFiles();
1475
0
    if (!rpURLList.hasElements())
1476
0
        return ERRCODE_ABORT;
1477
1478
0
    uno::Reference<XFilePickerControlAccess> xCtrlAccess(mxFileDlg, UNO_QUERY);
1479
1480
    // create an itemset if there is no
1481
0
    if( !rpSet )
1482
0
        rpSet.emplace( SfxGetpApp()->GetPool() );
1483
1484
    // the item should remain only if it was set by the dialog
1485
0
    rpSet->ClearItem( SID_SELECTION );
1486
1487
0
    if (mbExport && mbHasSelectionBox && xCtrlAccess)
1488
0
    {
1489
0
        try
1490
0
        {
1491
0
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 );
1492
0
            bool bSelection = false;
1493
0
            if ( aValue >>= bSelection )
1494
0
                rpSet->Put( SfxBoolItem( SID_SELECTION, bSelection ) );
1495
0
        }
1496
0
        catch( const IllegalArgumentException& )
1497
0
        {
1498
0
            TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1499
0
        }
1500
0
    }
1501
1502
1503
    // set the read-only flag. When inserting a file, this flag is always set
1504
0
    if ( mbInsert )
1505
0
        rpSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
1506
0
    else if ( ( FILEOPEN_READONLY_VERSION == m_nDialogType ) && xCtrlAccess.is() )
1507
0
    {
1508
0
        try
1509
0
        {
1510
0
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 );
1511
0
            bool bReadOnly = false;
1512
0
            if ( ( aValue >>= bReadOnly ) && bReadOnly )
1513
0
                rpSet->Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) );
1514
0
        }
1515
0
        catch( const IllegalArgumentException& )
1516
0
        {
1517
0
            TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1518
0
        }
1519
0
    }
1520
0
    if ( mbHasVersions && xCtrlAccess.is() )
1521
0
    {
1522
0
        try
1523
0
        {
1524
0
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
1525
0
                                                ControlActions::GET_SELECTED_ITEM_INDEX );
1526
0
            sal_Int32 nVersion = 0;
1527
0
            if ( ( aValue >>= nVersion ) && nVersion > 0 )
1528
                // open a special version; 0 == current version
1529
0
                rpSet->Put( SfxInt16Item( SID_VERSION, static_cast<short>(nVersion) ) );
1530
0
        }
1531
0
        catch( const IllegalArgumentException& ){}
1532
0
    }
1533
1534
    // set the filter
1535
0
    getRealFilter( rFilter );
1536
1537
0
    std::shared_ptr<const SfxFilter> pCurrentFilter = getCurrentSfxFilter();
1538
1539
    // check, whether or not we have to display a password box
1540
0
    if ( pCurrentFilter && mbHasPassword && mbIsPwdEnabled && xCtrlAccess.is() )
1541
0
    {
1542
0
        try
1543
0
        {
1544
0
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
1545
0
            bool bPassWord = false;
1546
0
            if ( ( aValue >>= bPassWord ) && bPassWord )
1547
0
            {
1548
0
                SvtSaveOptions::ODFSaneDefaultVersion nVersion{
1549
0
                    SvtSaveOptions::ODFSVER_LATEST_EXTENDED};
1550
0
                if (!comphelper::IsFuzzing())
1551
0
                {
1552
0
                    nVersion = GetODFSaneDefaultVersion();
1553
0
                }
1554
                // old per-zip-entry ODF encryption destroys macro signatures
1555
0
                if (!::sfx2::UseODFWholesomeEncryption(nVersion)
1556
0
                    && (   SignatureState::OK == nScriptingSignatureState
1557
0
                        || SignatureState::INVALID == nScriptingSignatureState
1558
0
                        || SignatureState::NOTVALIDATED == nScriptingSignatureState
1559
0
                        || SignatureState::PARTIAL_OK == nScriptingSignatureState))
1560
0
                {
1561
0
                    std::unique_ptr<weld::MessageDialog> xBox(
1562
0
                        Application::CreateMessageDialog(mpFrameWeld,
1563
0
                            VclMessageType::Question, VclButtonsType::YesNo,
1564
0
                            SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSCRIPTINGSIGNATURE)));
1565
0
                    if (xBox->run() == RET_NO)
1566
0
                    {
1567
0
                        bPassWord = false;
1568
0
                    }
1569
0
                }
1570
0
            }
1571
1572
0
            if (bPassWord)
1573
0
            {
1574
                // ask for a password
1575
0
                const OUString& aDocName(rpURLList[0]);
1576
                // TODO: tdf#158839 problem: Also asks for a password if CHECKBOX_GPGENCRYPTION && CHECKBOX_PASSWORD
1577
                //       are checked. But only encrypts using GPG and discards the password.
1578
0
                ErrCode errCode = RequestPassword(pCurrentFilter, aDocName, &*rpSet, GetFrameInterface());
1579
0
                if (errCode != ERRCODE_NONE)
1580
0
                    return errCode;
1581
0
            }
1582
0
        }
1583
0
        catch( const IllegalArgumentException& ){}
1584
0
    }
1585
    // check, whether or not we have to display a key selection box
1586
0
    if ( pCurrentFilter && mbHasPassword && xCtrlAccess.is() )
1587
0
    {
1588
0
        try
1589
0
        {
1590
0
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION, 0 );
1591
0
            bool bGpg = false;
1592
0
            if ( ( aValue >>= bGpg ) && bGpg )
1593
0
            {
1594
0
                uno::Sequence< beans::NamedValue > aEncryptionData;
1595
0
                while(true)
1596
0
                {
1597
0
                    try
1598
0
                    {
1599
                        // ask for keys
1600
0
                        aEncryptionData
1601
0
                            = ::comphelper::OStorageHelper::CreateGpgPackageEncryptionData(
1602
0
                                GetFrameInterface());
1603
0
                        break; // user cancelled or we've some keys now
1604
0
                    }
1605
0
                    catch( const IllegalArgumentException& )
1606
0
                    {
1607
0
                        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(mpFrameWeld,
1608
0
                                                                                 VclMessageType::Warning, VclButtonsType::Ok,
1609
0
                                                                                 SfxResId(RID_SVXSTR_GPG_ENCRYPT_FAILURE)));
1610
0
                        xBox->run();
1611
0
                    }
1612
0
                }
1613
1614
0
                if ( aEncryptionData.hasElements() )
1615
0
                    rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::Any( aEncryptionData) ) );
1616
0
                else
1617
0
                    return ERRCODE_ABORT;
1618
0
            }
1619
0
        }
1620
0
        catch( const IllegalArgumentException& ){}
1621
0
    }
1622
0
    if ( pCurrentFilter && xCtrlAccess.is() )
1623
0
    {
1624
0
        try
1625
0
        {
1626
0
            Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN, 0 );
1627
0
            bool bSign = false;
1628
0
            if ((aValue >>= bSign) && bSign)
1629
0
            {
1630
0
                rpSet->Put(SfxBoolItem(SID_GPGSIGN, bSign));
1631
0
            }
1632
0
        }
1633
0
        catch( const IllegalArgumentException& ){}
1634
0
    }
1635
1636
0
    SaveLastUsedFilter();
1637
0
    return ERRCODE_NONE;
1638
0
}
1639
1640
ErrCode FileDialogHelper_Impl::execute()
1641
0
{
1642
0
    if ( ! mxFileDlg.is() )
1643
0
        return ERRCODE_ABORT;
1644
1645
0
    sal_Int16 nRet = implDoExecute();
1646
1647
0
    maPath = mxFileDlg->getDisplayDirectory();
1648
1649
0
    if ( ExecutableDialogResults::CANCEL == nRet )
1650
0
        return ERRCODE_ABORT;
1651
0
    else
1652
0
    {
1653
0
        return ERRCODE_NONE;
1654
0
    }
1655
0
}
1656
1657
OUString FileDialogHelper_Impl::getPath() const
1658
0
{
1659
0
    OUString aPath;
1660
1661
0
    if ( mxFileDlg.is() )
1662
0
        aPath = mxFileDlg->getDisplayDirectory();
1663
1664
0
    if ( aPath.isEmpty() )
1665
0
        aPath = maPath;
1666
1667
0
    return aPath;
1668
0
}
1669
1670
OUString FileDialogHelper_Impl::getFilter() const
1671
0
{
1672
0
    OUString aFilter = getCurrentFilterUIName();
1673
1674
0
    if( aFilter.isEmpty() )
1675
0
        aFilter = maCurFilter;
1676
1677
0
    return aFilter;
1678
0
}
1679
1680
void FileDialogHelper_Impl::getRealFilter( OUString& _rFilter ) const
1681
0
{
1682
0
    _rFilter = getCurrentFilterUIName();
1683
1684
0
    if ( _rFilter.isEmpty() )
1685
0
        _rFilter = maCurFilter;
1686
1687
0
    if ( !_rFilter.isEmpty() && mpMatcher )
1688
0
    {
1689
0
        std::shared_ptr<const SfxFilter> pFilter =
1690
0
            mpMatcher->GetFilter4UIName( _rFilter, m_nMustFlags, m_nDontFlags );
1691
0
        _rFilter = pFilter ? pFilter->GetFilterName() : OUString();
1692
0
    }
1693
0
}
1694
1695
void FileDialogHelper_Impl::verifyPath()
1696
0
{
1697
0
#ifdef UNX
1698
    // lp#905355, fdo#43895
1699
    // Check that the file has read only permission and is in /tmp -- this is
1700
    //  the case if we have opened the file from the web with firefox only.
1701
0
    if (maFileName.isEmpty()) {
1702
0
        return;
1703
0
    }
1704
0
    INetURLObject url(maPath);
1705
0
    if (url.GetProtocol() != INetProtocol::File
1706
0
        || url.getName(0, true, INetURLObject::DecodeMechanism::WithCharset) != "tmp")
1707
0
    {
1708
0
        return;
1709
0
    }
1710
0
    if (maFileName.indexOf('/') != -1) {
1711
0
        SAL_WARN("sfx.dialog", maFileName << " contains /");
1712
0
        return;
1713
0
    }
1714
0
    url.insertName(
1715
0
        maFileName, false, INetURLObject::LAST_SEGMENT,
1716
0
        INetURLObject::EncodeMechanism::All);
1717
0
    OUString sysPathU;
1718
0
    osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL(
1719
0
        url.GetMainURL(INetURLObject::DecodeMechanism::NONE), sysPathU);
1720
0
    if (e != osl::FileBase::E_None) {
1721
0
        SAL_WARN(
1722
0
            "sfx.dialog",
1723
0
            "getSystemPathFromFileURL("
1724
0
                << url.GetMainURL(INetURLObject::DecodeMechanism::NONE) << ") failed with "
1725
0
                << +e);
1726
0
        return;
1727
0
    }
1728
0
    OString sysPathC;
1729
0
    if (!sysPathU.convertToString(
1730
0
            &sysPathC, osl_getThreadTextEncoding(),
1731
0
            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1732
0
             | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1733
0
    {
1734
0
        SAL_WARN(
1735
0
            "sfx.dialog",
1736
0
            "convertToString(" << sysPathU << ") failed for encoding "
1737
0
                << +osl_getThreadTextEncoding());
1738
0
        return;
1739
0
    }
1740
0
    struct stat aFileStat;
1741
0
    if (stat(sysPathC.getStr(), &aFileStat) == -1) {
1742
0
        SAL_WARN( "sfx.dialog", "stat(" << sysPathC << ") failed with errno " << errno);
1743
0
        return;
1744
0
    }
1745
0
    if ((aFileStat.st_mode & (S_IRWXO | S_IRWXG | S_IRWXU)) == S_IRUSR) {
1746
0
        maPath = SvtPathOptions().GetWorkPath();
1747
0
        mxFileDlg->setDisplayDirectory( maPath );
1748
0
    }
1749
#else
1750
    (void) this;
1751
#endif
1752
0
}
1753
1754
void FileDialogHelper_Impl::displayFolder( const OUString& _rPath )
1755
0
{
1756
0
    if ( _rPath.isEmpty() )
1757
        // nothing to do
1758
0
        return;
1759
1760
0
    maPath = _rPath;
1761
0
    if ( mxFileDlg.is() )
1762
0
    {
1763
0
        try
1764
0
        {
1765
0
            mxFileDlg->setDisplayDirectory( maPath );
1766
0
            verifyPath();
1767
0
        }
1768
0
        catch( const IllegalArgumentException& )
1769
0
        {
1770
0
            TOOLS_WARN_EXCEPTION( "sfx", "FileDialogHelper_Impl::displayFolder" );
1771
0
        }
1772
0
    }
1773
0
}
1774
1775
void FileDialogHelper_Impl::setFileName( const OUString& _rFile )
1776
0
{
1777
0
    maFileName = _rFile;
1778
0
    if ( mxFileDlg.is() )
1779
0
    {
1780
0
        try
1781
0
        {
1782
0
            mxFileDlg->setDefaultName( maFileName );
1783
0
            verifyPath();
1784
0
        }
1785
0
        catch( const IllegalArgumentException& )
1786
0
        {
1787
0
            TOOLS_WARN_EXCEPTION( "sfx", "FileDialogHelper_Impl::setFileName" );
1788
0
        }
1789
0
    }
1790
0
}
1791
1792
void FileDialogHelper_Impl::setFilter( const OUString& rFilter )
1793
0
{
1794
0
    DBG_ASSERT( rFilter.indexOf(':') == -1, "Old filter name used!");
1795
1796
0
    maCurFilter = rFilter;
1797
1798
0
    if ( !rFilter.isEmpty() && mpMatcher )
1799
0
    {
1800
0
        std::shared_ptr<const SfxFilter> pFilter = mpMatcher->GetFilter4FilterName(
1801
0
                                        rFilter, m_nMustFlags, m_nDontFlags );
1802
0
        if ( pFilter )
1803
0
            maCurFilter = pFilter->GetUIName();
1804
0
    }
1805
1806
0
    if ( !maCurFilter.isEmpty() && mxFileDlg.is() )
1807
0
    {
1808
0
        try
1809
0
        {
1810
0
            mxFileDlg->setCurrentFilter( maCurFilter );
1811
0
        }
1812
0
        catch( const IllegalArgumentException& ){}
1813
0
    }
1814
0
}
1815
1816
void FileDialogHelper_Impl::createMatcher( const OUString& rFactory )
1817
0
{
1818
0
    if (mbDeleteMatcher)
1819
0
        delete mpMatcher;
1820
1821
0
    mpMatcher = new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) );
1822
0
    mbDeleteMatcher = true;
1823
0
}
1824
1825
void FileDialogHelper_Impl::addFilters( const OUString& rFactory,
1826
                                        SfxFilterFlags nMust,
1827
                                        SfxFilterFlags nDont )
1828
0
{
1829
0
    if ( ! mxFileDlg.is() )
1830
0
        return;
1831
1832
0
    if (mbDeleteMatcher)
1833
0
        delete mpMatcher;
1834
1835
    // we still need a matcher to convert UI names to filter names
1836
0
    if ( rFactory.isEmpty() )
1837
0
    {
1838
0
        SfxApplication *pSfxApp = SfxGetpApp();
1839
0
        mpMatcher = &pSfxApp->GetFilterMatcher();
1840
0
        mbDeleteMatcher = false;
1841
0
    }
1842
0
    else
1843
0
    {
1844
0
        mpMatcher = new SfxFilterMatcher( rFactory );
1845
0
        mbDeleteMatcher = true;
1846
0
    }
1847
1848
0
    uno::Reference< XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1849
0
    uno::Reference< XContainerQuery > xFilterCont(
1850
0
        xSMGR->createInstance(u"com.sun.star.document.FilterFactory"_ustr),
1851
0
        UNO_QUERY);
1852
0
    if ( ! xFilterCont.is() )
1853
0
        return;
1854
1855
0
    m_nMustFlags |= nMust;
1856
0
    m_nDontFlags |= nDont;
1857
1858
    // create the list of filters
1859
0
    OUString sQuery =
1860
0
        "getSortedFilterList()"
1861
0
        ":module=" +
1862
0
        rFactory + // use long name here !
1863
0
        ":iflags=" +
1864
0
        OUString::number(static_cast<sal_Int32>(m_nMustFlags)) +
1865
0
        ":eflags=" +
1866
0
        OUString::number(static_cast<sal_Int32>(m_nDontFlags));
1867
1868
0
    uno::Reference< XEnumeration > xResult;
1869
0
    try
1870
0
    {
1871
0
        xResult = xFilterCont->createSubSetEnumerationByQuery(sQuery);
1872
0
    }
1873
0
    catch( const uno::Exception& )
1874
0
    {
1875
0
        SAL_WARN( "sfx.dialog", "Could not get filters from the configuration!" );
1876
0
    }
1877
1878
0
    TSortedFilterList         aIter   (xResult);
1879
1880
    // append the filters
1881
0
    OUString sFirstFilter;
1882
0
    if (open_or_save_t::OPEN == lcl_OpenOrSave(m_nDialogType))
1883
0
        ::sfx2::appendFiltersForOpen( aIter, mxFileDlg, sFirstFilter, *this );
1884
0
    else if ( mbExport )
1885
0
        ::sfx2::appendExportFilters( aIter, mxFileDlg, sFirstFilter, *this );
1886
0
    else
1887
0
        ::sfx2::appendFiltersForSave( aIter, mxFileDlg, sFirstFilter, *this, rFactory );
1888
1889
    // set our initial selected filter (if we do not already have one)
1890
0
    if ( maSelectFilter.isEmpty() )
1891
0
        maSelectFilter = sFirstFilter;
1892
0
}
1893
1894
void FileDialogHelper_Impl::addFilter( const OUString& rFilterName,
1895
                                       const OUString& rExtension )
1896
0
{
1897
0
    if ( ! mxFileDlg.is() )
1898
0
        return;
1899
1900
0
    try
1901
0
    {
1902
0
        mxFileDlg->appendFilter( rFilterName, rExtension );
1903
1904
0
        if ( maSelectFilter.isEmpty() )
1905
0
            maSelectFilter = rFilterName;
1906
0
    }
1907
0
    catch( const IllegalArgumentException& )
1908
0
    {
1909
0
        SAL_WARN( "sfx.dialog", "Could not append Filter" << rFilterName );
1910
0
    }
1911
0
}
1912
1913
void FileDialogHelper_Impl::addGraphicFilter()
1914
0
{
1915
0
    if ( ! mxFileDlg.is() )
1916
0
        return;
1917
1918
    // create the list of filters
1919
0
    mpGraphicFilter.reset( new GraphicFilter );
1920
0
    sal_uInt16 i, j, nCount = mpGraphicFilter->GetImportFormatCount();
1921
1922
    // compute the extension string for all known import filters
1923
0
    OUString aExtensions;
1924
1925
0
    for ( i = 0; i < nCount; i++ )
1926
0
    {
1927
0
        j = 0;
1928
0
        while( true )
1929
0
        {
1930
0
            OUString sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ );
1931
0
            if ( sWildcard.isEmpty() )
1932
0
                break;
1933
0
            if ( aExtensions.indexOf( sWildcard ) == -1 )
1934
0
            {
1935
0
                if ( !aExtensions.isEmpty() )
1936
0
                    aExtensions += ";";
1937
0
                aExtensions += sWildcard;
1938
0
            }
1939
0
        }
1940
0
    }
1941
1942
#if defined(_WIN32)
1943
    if ( aExtensions.getLength() > 240 )
1944
        aExtensions = FILEDIALOG_FILTER_ALL;
1945
#endif
1946
0
    bool bIsInOpenMode = isInOpenMode();
1947
1948
0
    try
1949
0
    {
1950
        // if the extension is not "All files", insert "All images"
1951
0
        if (aExtensions != FILEDIALOG_FILTER_ALL)
1952
0
        {
1953
0
            OUString aAllFilterName = SfxResId(STR_SFX_IMPORT_ALL_IMAGES);
1954
0
            aAllFilterName = ::sfx2::addExtension( aAllFilterName, aExtensions, bIsInOpenMode, *this );
1955
0
            mxFileDlg->appendFilter( aAllFilterName, aExtensions );
1956
0
            maSelectFilter = aAllFilterName; // and make it the default
1957
0
        }
1958
1959
        // rhbz#1715109 always include All files *.* or *
1960
0
        OUString aAllFilesName = SfxResId( STR_SFX_FILTERNAME_ALL );
1961
0
        aAllFilesName = ::sfx2::addExtension( aAllFilesName, FILEDIALOG_FILTER_ALL, bIsInOpenMode, *this );
1962
0
        mxFileDlg->appendFilter( aAllFilesName, FILEDIALOG_FILTER_ALL );
1963
1964
        // if the extension is "All files", make that the default
1965
0
        if (aExtensions == FILEDIALOG_FILTER_ALL)
1966
0
            maSelectFilter = aAllFilesName;
1967
0
    }
1968
0
    catch( const IllegalArgumentException& )
1969
0
    {
1970
0
        SAL_WARN( "sfx.dialog", "Could not append Filter" );
1971
0
    }
1972
1973
    // Now add the filter
1974
0
    for ( i = 0; i < nCount; i++ )
1975
0
    {
1976
0
        OUString aName = mpGraphicFilter->GetImportFormatName( i );
1977
0
        OUString aExt;
1978
0
        j = 0;
1979
0
        while( true )
1980
0
        {
1981
0
            OUString sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ );
1982
0
            if ( sWildcard.isEmpty() )
1983
0
                break;
1984
0
            if ( aExt.indexOf( sWildcard ) == -1 )
1985
0
            {
1986
0
                if ( !aExt.isEmpty() )
1987
0
                    aExt += ";";
1988
0
                aExt += sWildcard;
1989
0
            }
1990
0
        }
1991
0
        aName = ::sfx2::addExtension( aName, aExt, bIsInOpenMode, *this );
1992
0
        try
1993
0
        {
1994
0
            mxFileDlg->appendFilter( aName, aExt );
1995
0
        }
1996
0
        catch( const IllegalArgumentException& )
1997
0
        {
1998
0
            SAL_WARN( "sfx.dialog", "Could not append Filter" );
1999
0
        }
2000
0
    }
2001
0
}
2002
2003
constexpr OUStringLiteral GRF_CONFIG_STR = u"   ";
2004
constexpr OUString STD_CONFIG_STR = u"1 "_ustr;
2005
2006
static void SetToken( OUString& rOrigStr, sal_Int32 nToken, sal_Unicode cTok, std::u16string_view rStr)
2007
0
{
2008
0
    const sal_Unicode*  pStr        = rOrigStr.getStr();
2009
0
    sal_Int32     nLen              = rOrigStr.getLength();
2010
0
    sal_Int32     nTok              = 0;
2011
0
    sal_Int32     nFirstChar        = 0;
2012
0
    sal_Int32     i                 = nFirstChar;
2013
2014
    // Determine token position and length
2015
0
    pStr += i;
2016
0
    while ( i < nLen )
2017
0
    {
2018
        // Increase token count if match
2019
0
        if ( *pStr == cTok )
2020
0
        {
2021
0
            ++nTok;
2022
2023
0
            if ( nTok == nToken )
2024
0
                nFirstChar = i+1;
2025
0
            else
2026
0
            {
2027
0
                if ( nTok > nToken )
2028
0
                    break;
2029
0
            }
2030
0
        }
2031
2032
0
        ++pStr;
2033
0
        ++i;
2034
0
    }
2035
2036
0
    if ( nTok >= nToken )
2037
0
        rOrigStr = rOrigStr.replaceAt( nFirstChar, i-nFirstChar, rStr );
2038
0
}
2039
2040
namespace
2041
{
2042
void SaveLastDirectory(OUString const& sContext, OUString const& sDirectory)
2043
0
{
2044
0
    if (sContext.isEmpty())
2045
0
        return;
2046
2047
0
    std::shared_ptr<comphelper::ConfigurationChanges> batch(
2048
0
        comphelper::ConfigurationChanges::create());
2049
0
    Reference<container::XNameContainer> set(
2050
0
        officecfg::Office::Common::Misc::FilePickerLastDirectory::get(batch));
2051
2052
0
    bool found;
2053
0
    Any v;
2054
0
    try
2055
0
    {
2056
0
        v = set->getByName(sContext);
2057
0
        found = true;
2058
0
    }
2059
0
    catch (container::NoSuchElementException&)
2060
0
    {
2061
0
        found = false;
2062
0
    }
2063
0
    if (found)
2064
0
    {
2065
0
        Reference<XPropertySet> el(v.get<Reference<XPropertySet>>(), UNO_SET_THROW);
2066
0
        el->setPropertyValue(u"LastPath"_ustr, Any(sDirectory));
2067
0
    }
2068
0
    else
2069
0
    {
2070
0
        Reference<XPropertySet> el(
2071
0
            (Reference<lang::XSingleServiceFactory>(set, UNO_QUERY_THROW)->createInstance()),
2072
0
            UNO_QUERY_THROW);
2073
0
        el->setPropertyValue(u"LastPath"_ustr, Any(sDirectory));
2074
0
        Any v2(el);
2075
0
        set->insertByName(sContext, v2);
2076
0
    }
2077
0
    batch->commit();
2078
0
}
2079
}
2080
2081
void FileDialogHelper_Impl::saveConfig()
2082
0
{
2083
0
    uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
2084
2085
0
    if ( ! xDlg.is() )
2086
0
        return;
2087
2088
0
    if ( mbHasPreview )
2089
0
    {
2090
0
        SvtViewOptions aDlgOpt( EViewType::Dialog, IMPGRF_CONFIGNAME );
2091
2092
0
        try
2093
0
        {
2094
            // tdf#61358 - remember the last "insert as link" state
2095
0
            bool bLink = false;
2096
0
            xDlg->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bLink;
2097
0
            OUString aUserData(GRF_CONFIG_STR);
2098
0
            SetToken(aUserData, 0, ' ', OUString::number(static_cast<sal_Int32>(bLink)));
2099
2100
0
            bool bValue = false;
2101
0
            xDlg->getValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0) >>= bValue;
2102
0
            SetToken( aUserData, 1, ' ', OUString::number( static_cast<sal_Int32>(bValue) ) );
2103
2104
0
            INetURLObject aObj( getPath() );
2105
2106
0
            if ( aObj.GetProtocol() == INetProtocol::File )
2107
0
                SetToken( aUserData, 2, ' ', aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2108
2109
0
            OUString aFilter = getFilter();
2110
0
            aFilter = EncodeSpaces_Impl( aFilter );
2111
0
            SetToken( aUserData, 3, ' ', aFilter );
2112
2113
0
            aDlgOpt.SetUserItem( USERITEM_NAME, Any( aUserData ) );
2114
0
        }
2115
0
        catch( const IllegalArgumentException& ){}
2116
0
    }
2117
0
    else
2118
0
    {
2119
0
        bool bWriteConfig = false;
2120
0
        SvtViewOptions aDlgOpt( EViewType::Dialog, IODLG_CONFIGNAME );
2121
0
        OUString aUserData(STD_CONFIG_STR);
2122
2123
0
        if ( aDlgOpt.Exists() )
2124
0
        {
2125
0
            Any aUserItem = aDlgOpt.GetUserItem( USERITEM_NAME );
2126
0
            OUString aTemp;
2127
0
            if ( aUserItem >>= aTemp )
2128
0
                aUserData = aTemp;
2129
0
        }
2130
2131
0
        if ( mbHasAutoExt )
2132
0
        {
2133
0
            try
2134
0
            {
2135
0
                bool bAutoExt = true;
2136
0
                xDlg->getValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0) >>= bAutoExt;
2137
0
                SetToken( aUserData, 0, ' ', OUString::number( static_cast<sal_Int32>(bAutoExt) ) );
2138
0
                bWriteConfig = true;
2139
0
            }
2140
0
            catch( const IllegalArgumentException& ){}
2141
0
        }
2142
2143
0
        if ( ! mbIsSaveDlg )
2144
0
        {
2145
0
            OUString aPath = getPath();
2146
0
            if ( comphelper::isFileUrl( aPath ) )
2147
0
            {
2148
0
                SetToken( aUserData, 1, ' ', aPath );
2149
0
                bWriteConfig = true;
2150
0
            }
2151
0
        }
2152
2153
0
        if( mbHasSelectionBox && mbSelectionFltrEnabled )
2154
0
        {
2155
0
            try
2156
0
            {
2157
0
                bool bSelection = true;
2158
0
                xDlg->getValue(ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0) >>= bSelection;
2159
0
                if ( comphelper::string::getTokenCount(aUserData, ' ') < 3 )
2160
0
                    aUserData += " ";
2161
0
                SetToken( aUserData, 2, ' ', OUString::number( static_cast<sal_Int32>(bSelection) ) );
2162
0
                bWriteConfig = true;
2163
0
            }
2164
0
            catch( const IllegalArgumentException& ){}
2165
0
        }
2166
2167
0
        if ( bWriteConfig )
2168
0
            aDlgOpt.SetUserItem( USERITEM_NAME, Any( aUserData ) );
2169
0
    }
2170
2171
    // Store to config, if explicit context is set (and default directory is not given)
2172
0
    if (meContext != FileDialogHelper::UnknownContext && msPreselectedDir.isEmpty())
2173
0
    {
2174
0
        SaveLastDirectory(FileDialogHelper::contextToString(meContext), getPath());
2175
0
    }
2176
0
}
2177
2178
OUString FileDialogHelper_Impl::getInitPath(std::u16string_view _rFallback,
2179
                                            const sal_Int32 _nFallbackToken)
2180
0
{
2181
0
    OUString sPath;
2182
    // Load from config, if explicit context is set. Otherwise load from (global) runtime var.
2183
0
    if (meContext == FileDialogHelper::UnknownContext || !msPreselectedDir.isEmpty())
2184
0
    {
2185
        // For export, the default directory is passed on
2186
0
        sPath = msPreselectedDir;
2187
0
    }
2188
0
    else
2189
0
    {
2190
0
        OUString sContext = FileDialogHelper::contextToString(meContext);
2191
0
        Reference<XNameAccess> set(officecfg::Office::Common::Misc::FilePickerLastDirectory::get());
2192
0
        Any v;
2193
0
        try
2194
0
        {
2195
0
            v = set->getByName(sContext);
2196
0
            Reference<XPropertySet> el(v.get<Reference<XPropertySet>>(), UNO_SET_THROW);
2197
0
            sPath = el->getPropertyValue(u"LastPath"_ustr).get<OUString>();
2198
0
        }
2199
0
        catch (NoSuchElementException&)
2200
0
        {
2201
0
        }
2202
0
    }
2203
2204
0
    if ( sPath.isEmpty() )
2205
0
        sPath = o3tl::getToken(_rFallback, _nFallbackToken, ' ' );
2206
2207
    // check if the path points to a valid (accessible) directory
2208
0
    bool bValid = false;
2209
0
    if ( !sPath.isEmpty() )
2210
0
    {
2211
0
        OUString sPathCheck( sPath );
2212
0
        if ( sPathCheck[ sPathCheck.getLength() - 1 ] != '/' )
2213
0
            sPathCheck += "/";
2214
0
        sPathCheck += ".";
2215
0
        try
2216
0
        {
2217
0
            ::ucbhelper::Content aContent( sPathCheck,
2218
0
                                            utl::UCBContentHelper::getDefaultCommandEnvironment(),
2219
0
                                            comphelper::getProcessComponentContext() );
2220
0
            bValid = aContent.isFolder();
2221
0
        }
2222
0
        catch( const Exception& ) {}
2223
0
    }
2224
0
    if ( !bValid )
2225
0
        sPath.clear();
2226
0
    return sPath;
2227
0
}
2228
2229
void FileDialogHelper_Impl::loadConfig()
2230
0
{
2231
0
    uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY );
2232
0
    Any aValue;
2233
2234
0
    if ( ! xDlg.is() )
2235
0
        return;
2236
2237
0
    if ( mbHasPreview )
2238
0
    {
2239
0
        SvtViewOptions aViewOpt( EViewType::Dialog, IMPGRF_CONFIGNAME );
2240
0
        OUString aUserData;
2241
2242
0
        if ( aViewOpt.Exists() )
2243
0
        {
2244
0
            Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
2245
0
            OUString aTemp;
2246
0
            if ( aUserItem >>= aTemp )
2247
0
                aUserData = aTemp;
2248
0
        }
2249
2250
0
        if ( !aUserData.isEmpty() )
2251
0
        {
2252
0
            try
2253
0
            {
2254
                // respect the last "insert as link" state
2255
0
                bool bLink = o3tl::toInt32(o3tl::getToken(aUserData, 0, ' ' ));
2256
0
                aValue <<= bLink;
2257
0
                xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, aValue );
2258
2259
                // respect the last "show preview" state
2260
0
                bool bShowPreview = o3tl::toInt32(o3tl::getToken(aUserData, 1, ' ' ));
2261
0
                aValue <<= bShowPreview;
2262
0
                xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, aValue );
2263
2264
0
                if ( maPath.isEmpty() )
2265
0
                    displayFolder( getInitPath( aUserData, 2 ) );
2266
2267
0
                if ( maCurFilter.isEmpty() )
2268
0
                {
2269
0
                    OUString aFilter = aUserData.getToken( 3, ' ' );
2270
0
                    aFilter = DecodeSpaces_Impl( aFilter );
2271
0
                    setFilter( aFilter );
2272
0
                }
2273
2274
                // set the member so we know that we have to show the preview
2275
0
                mbShowPreview = bShowPreview;
2276
0
            }
2277
0
            catch( const IllegalArgumentException& ){}
2278
0
        }
2279
2280
0
        if ( maPath.isEmpty() )
2281
0
            displayFolder( SvtPathOptions().GetWorkPath() );
2282
0
    }
2283
0
    else
2284
0
    {
2285
0
        SvtViewOptions aViewOpt( EViewType::Dialog, IODLG_CONFIGNAME );
2286
0
        OUString aUserData;
2287
2288
0
        if ( aViewOpt.Exists() )
2289
0
        {
2290
0
            Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
2291
0
            OUString aTemp;
2292
0
            if ( aUserItem >>= aTemp )
2293
0
                aUserData = aTemp;
2294
0
        }
2295
2296
0
        if ( aUserData.isEmpty() )
2297
0
            aUserData = STD_CONFIG_STR;
2298
2299
0
        if ( maPath.isEmpty() )
2300
0
            displayFolder( getInitPath( aUserData, 1 ) );
2301
2302
0
        if ( mbHasAutoExt )
2303
0
        {
2304
0
            sal_Int32 nFlag = o3tl::toInt32(o3tl::getToken(aUserData, 0, ' ' ));
2305
0
            aValue <<= static_cast<bool>(nFlag);
2306
0
            try
2307
0
            {
2308
0
                xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue );
2309
0
            }
2310
0
            catch( const IllegalArgumentException& ){}
2311
0
        }
2312
2313
0
        if( mbHasSelectionBox )
2314
0
        {
2315
0
            sal_Int32 nFlag = o3tl::toInt32(o3tl::getToken(aUserData, 2, ' ' ));
2316
0
            aValue <<= static_cast<bool>(nFlag);
2317
0
            try
2318
0
            {
2319
0
                xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, aValue );
2320
0
            }
2321
0
            catch( const IllegalArgumentException& ){}
2322
0
        }
2323
2324
0
        if ( maPath.isEmpty() )
2325
0
            displayFolder( SvtPathOptions().GetWorkPath() );
2326
0
    }
2327
0
}
2328
2329
void FileDialogHelper_Impl::setDefaultValues()
2330
0
{
2331
    // when no filter is set, we set the currentFilter to <all>
2332
0
    if ( maCurFilter.isEmpty() && !maSelectFilter.isEmpty() )
2333
0
    {
2334
0
        try
2335
0
        {
2336
0
            mxFileDlg->setCurrentFilter( maSelectFilter );
2337
0
        }
2338
0
        catch( const IllegalArgumentException& )
2339
0
        {}
2340
0
    }
2341
2342
    // when no path is set, we use the standard 'work' folder
2343
0
    if ( maPath.isEmpty() )
2344
0
    {
2345
0
        OUString aWorkFolder = SvtPathOptions().GetWorkPath();
2346
0
        try
2347
0
        {
2348
0
            mxFileDlg->setDisplayDirectory( aWorkFolder );
2349
0
        }
2350
0
        catch( const Exception& )
2351
0
        {
2352
0
            TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" );
2353
0
        }
2354
0
    }
2355
0
}
2356
2357
bool FileDialogHelper_Impl::isShowFilterExtensionEnabled() const
2358
0
{
2359
0
    return !maFilters.empty();
2360
0
}
2361
2362
void FileDialogHelper_Impl::addFilterPair( const OUString& rFilter,
2363
                                           const OUString& rFilterWithExtension )
2364
0
{
2365
0
    maFilters.emplace_back( rFilter, rFilterWithExtension );
2366
2367
0
}
2368
2369
OUString FileDialogHelper_Impl::getFilterName( std::u16string_view rFilterWithExtension ) const
2370
0
{
2371
0
    OUString sRet;
2372
0
    for (auto const& filter : maFilters)
2373
0
    {
2374
0
        if (filter.Second == rFilterWithExtension)
2375
0
        {
2376
0
            sRet = filter.First;
2377
0
            break;
2378
0
        }
2379
0
    }
2380
0
    return sRet;
2381
0
}
2382
2383
OUString FileDialogHelper_Impl::getFilterWithExtension( std::u16string_view rFilter ) const
2384
0
{
2385
0
    OUString sRet;
2386
0
    for (auto const& filter : maFilters)
2387
0
    {
2388
0
        if ( filter.First == rFilter )
2389
0
        {
2390
0
            sRet = filter.Second;
2391
0
            break;
2392
0
        }
2393
0
    }
2394
0
    return sRet;
2395
0
}
2396
2397
void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext )
2398
0
{
2399
0
    meContext = _eNewContext;
2400
2401
0
    std::optional<OUString> pConfigId = GetLastFilterConfigId( _eNewContext );
2402
0
    if( pConfigId )
2403
0
        LoadLastUsedFilter( *pConfigId );
2404
0
}
2405
2406
// FileDialogHelper
2407
2408
FileDialogHelper::FileDialogHelper(
2409
    sal_Int16 nDialogType,
2410
    FileDialogFlags nFlags,
2411
    const OUString& rFact,
2412
    SfxFilterFlags nMust,
2413
    SfxFilterFlags nDont,
2414
    weld::Window* pPreferredParent)
2415
0
    :   m_nError(0),
2416
0
        mpImpl(new FileDialogHelper_Impl(this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, pPreferredParent))
2417
0
{
2418
2419
    // create the list of filters
2420
0
    mpImpl->addFilters(
2421
0
            SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2422
0
}
2423
2424
FileDialogHelper::FileDialogHelper(
2425
    sal_Int16 nDialogType,
2426
    FileDialogFlags nFlags,
2427
    const OUString& rFact,
2428
    sal_Int16 nDialog,
2429
    SfxFilterFlags nMust,
2430
    SfxFilterFlags nDont,
2431
    const OUString& rPreselectedDir,
2432
    const css::uno::Sequence< OUString >& rDenyList,
2433
    weld::Window* pPreferredParent)
2434
0
    :   m_nError(0),
2435
0
        mpImpl( new FileDialogHelper_Impl( this, nDialogType, nFlags, nDialog, pPreferredParent, rPreselectedDir, rDenyList ) )
2436
0
{
2437
    // create the list of filters
2438
0
    mpImpl->addFilters(
2439
0
            SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont );
2440
0
}
2441
2442
FileDialogHelper::FileDialogHelper(sal_Int16 nDialogType, FileDialogFlags nFlags, weld::Window* pPreferredParent)
2443
0
    :   m_nError(0),
2444
0
        mpImpl( new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, pPreferredParent ) )
2445
0
{
2446
0
}
2447
2448
FileDialogHelper::FileDialogHelper(
2449
    sal_Int16 nDialogType,
2450
    FileDialogFlags nFlags,
2451
    const OUString& aFilterUIName,
2452
    std::u16string_view aExtName,
2453
    const OUString& rPreselectedDir,
2454
    const css::uno::Sequence< OUString >& rDenyList,
2455
    weld::Window* pPreferredParent )
2456
0
    :   m_nError(0),
2457
0
        mpImpl( new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, pPreferredParent, rPreselectedDir, rDenyList ) )
2458
0
{
2459
    // the wildcard here is expected in form "*.extension"
2460
0
    OUString aWildcard;
2461
0
    if ( aExtName.find( '*' ) != 0 )
2462
0
    {
2463
0
        if ( !aExtName.empty() && aExtName.find( '.' ) != 0 )
2464
0
            aWildcard = "*.";
2465
0
        else
2466
0
            aWildcard = "*";
2467
0
    }
2468
2469
0
    aWildcard += aExtName;
2470
2471
0
    OUString const aUIString = ::sfx2::addExtension(
2472
0
        aFilterUIName, aWildcard, (open_or_save_t::OPEN == lcl_OpenOrSave(mpImpl->m_nDialogType)), *mpImpl);
2473
0
    AddFilter( aUIString, aWildcard );
2474
0
}
2475
2476
FileDialogHelper::~FileDialogHelper()
2477
0
{
2478
0
    mpImpl->dispose();
2479
0
}
2480
2481
void FileDialogHelper::CreateMatcher( const OUString& rFactory )
2482
0
{
2483
0
    mpImpl->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) );
2484
0
}
2485
2486
void FileDialogHelper::SetControlHelpIds( const sal_Int16* _pControlId, const char** _pHelpId )
2487
0
{
2488
0
    mpImpl->setControlHelpIds( _pControlId, _pHelpId );
2489
0
}
2490
2491
void FileDialogHelper::SetContext( Context _eNewContext )
2492
0
{
2493
0
    mpImpl->SetContext( _eNewContext );
2494
0
}
2495
2496
OUString FileDialogHelper::contextToString(Context context)
2497
0
{
2498
    // These strings are used in the configuration, to store the last used directory for each context.
2499
    // Please don't change them.
2500
0
    switch(context) {
2501
0
        case AcceleratorConfig:
2502
0
            return u"AcceleratorConfig"_ustr;
2503
0
        case AutoRedact:
2504
0
            return u"AutoRedact"_ustr;
2505
0
        case BaseDataSource:
2506
0
            return u"BaseDataSource"_ustr;
2507
0
        case BaseSaveAs:
2508
0
            return u"BaseSaveAs"_ustr;
2509
0
        case BasicExportDialog:
2510
0
            return u"BasicExportDialog"_ustr;
2511
0
        case BasicExportPackage:
2512
0
            return u"BasicExportPackage"_ustr;
2513
0
        case BasicExportSource:
2514
0
            return u"BasicExportSource"_ustr;
2515
0
        case BasicImportDialog:
2516
0
            return u"BasicImportDialog"_ustr;
2517
0
        case BasicImportSource:
2518
0
            return u"BasicImportSource"_ustr;
2519
0
        case BasicInsertLib:
2520
0
            return u"BasicInsertLib"_ustr;
2521
0
        case BulletsAddImage:
2522
0
            return u"BulletsAddImage"_ustr;
2523
0
        case CalcDataProvider:
2524
0
            return u"CalcDataProvider"_ustr;
2525
0
        case CalcDataStream:
2526
0
            return u"CalcDataStream"_ustr;
2527
0
        case CalcExport:
2528
0
            return u"CalcExport"_ustr;
2529
0
        case CalcSaveAs:
2530
0
            return u"CalcSaveAs"_ustr;
2531
0
        case CalcXMLSource:
2532
0
            return u"CalcXMLSource"_ustr;
2533
0
        case ExportImage:
2534
0
            return u"ExportImage"_ustr;
2535
0
        case ExtensionManager:
2536
0
            return u"ExtensionManager"_ustr;
2537
0
        case FormsAddInstance:
2538
0
            return u"FormsAddInstance"_ustr;
2539
0
        case FormsInsertImage:
2540
0
            return u"FormsInsertImage"_ustr;
2541
0
        case LinkClientOLE:
2542
0
            return u"LinkClientOLE"_ustr;
2543
0
        case LinkClientFile:
2544
0
            return u"LinkClientFile"_ustr;
2545
0
        case DrawImpressInsertFile:
2546
0
            return u"DrawImpressInsertFile"_ustr;
2547
0
        case DrawImpressOpenSound:
2548
0
            return u"DrawImpressOpenSound"_ustr;
2549
0
        case DrawExport:
2550
0
            return u"DrawExport"_ustr;
2551
0
        case DrawSaveAs:
2552
0
            return u"DrawSaveAs"_ustr;
2553
0
        case IconImport:
2554
0
            return u"IconImport"_ustr;
2555
0
        case ImpressClickAction:
2556
0
            return u"ImpressClickAction"_ustr;
2557
0
        case ImpressExport:
2558
0
            return u"ImpressExport"_ustr;
2559
0
        case ImpressPhotoDialog:
2560
0
            return u"ImpressPhotoDialog"_ustr;
2561
0
        case ImpressSaveAs:
2562
0
            return u"ImpressSaveAs"_ustr;
2563
0
        case ImageMap:
2564
0
            return u"ImageMap"_ustr;
2565
0
        case InsertDoc:
2566
0
            return u"InsertDoc"_ustr;
2567
0
        case InsertImage:
2568
0
            return u"InsertImage"_ustr;
2569
0
        case InsertOLE:
2570
0
            return u"InsertOLE"_ustr;
2571
0
        case InsertMedia:
2572
0
            return u"InsertMedia"_ustr;
2573
0
        case JavaClassPath:
2574
0
            return u"JavaClassPath"_ustr;
2575
0
        case ReportInsertImage:
2576
0
            return u"ReportInsertImage"_ustr;
2577
0
        case ScreenshotAnnotation:
2578
0
            return u"ScreenshotAnnotation"_ustr;
2579
0
        case SignatureLine:
2580
0
            return u"SignatureLine"_ustr;
2581
0
        case TemplateImport:
2582
0
            return u"TemplateImport"_ustr;
2583
0
        case WriterCreateAddressList:
2584
0
            return u"WriterCreateAddressList"_ustr;
2585
0
        case WriterExport:
2586
0
            return u"WriterExport"_ustr;
2587
0
        case WriterImportAutotext:
2588
0
            return u"WriterImportAutotext"_ustr;
2589
0
        case WriterInsertImage:
2590
0
            return u"WriterInsertImage"_ustr;
2591
0
        case WriterInsertScript:
2592
0
            return u"WriterInsertScript"_ustr;
2593
0
        case WriterLoadTemplate:
2594
0
            return u"WriterLoadTemplate"_ustr;
2595
0
        case WriterMailMerge:
2596
0
            return u"WriterMailMerge"_ustr;
2597
0
        case WriterMailMergeSaveAs:
2598
0
            return u"WriterMailMergeSaveAs"_ustr;
2599
0
        case WriterNewHTMLGlobalDoc:
2600
0
            return u"WriterNewHTMLGlobalDoc"_ustr;
2601
0
        case WriterRegisterDataSource:
2602
0
            return u"WriterRegisterDataSource"_ustr;
2603
0
        case WriterSaveAs:
2604
0
            return u"WriterSaveAs"_ustr;
2605
0
        case WriterSaveHTML:
2606
0
            return u"WriterSaveHTML"_ustr;
2607
0
        case XMLFilterSettings:
2608
0
            return u"XMLFilterSettings"_ustr;
2609
0
        case UnknownContext:
2610
0
        default:
2611
0
            return u""_ustr;
2612
0
    }
2613
0
}
2614
2615
IMPL_LINK_NOARG(FileDialogHelper, ExecuteSystemFilePicker, void*, void)
2616
0
{
2617
0
    m_nError = mpImpl->execute();
2618
0
    m_aDialogClosedLink.Call( this );
2619
0
}
2620
2621
// rDirPath has to be a directory
2622
ErrCode FileDialogHelper::Execute( css::uno::Sequence<OUString>& rpURLList,
2623
                                   std::optional<SfxAllItemSet>& rpSet,
2624
                                   OUString&       rFilter,
2625
                                   const OUString& rDirPath )
2626
0
{
2627
0
    SetDisplayFolder( rDirPath );
2628
0
    return mpImpl->execute(rpURLList, rpSet, rFilter, SignatureState::UNKNOWN);
2629
0
}
2630
2631
2632
ErrCode FileDialogHelper::Execute()
2633
0
{
2634
0
    return mpImpl->execute();
2635
0
}
2636
2637
ErrCode FileDialogHelper::Execute( std::optional<SfxAllItemSet>& rpSet,
2638
                                   OUString&       rFilter,
2639
                                   SignatureState const nScriptingSignatureState)
2640
0
{
2641
0
    ErrCode nRet;
2642
0
    css::uno::Sequence<OUString> rURLList;
2643
0
    nRet = mpImpl->execute(rURLList, rpSet, rFilter, nScriptingSignatureState);
2644
0
    return nRet;
2645
0
}
2646
2647
void FileDialogHelper::StartExecuteModal( const Link<FileDialogHelper*,void>& rEndDialogHdl )
2648
0
{
2649
0
    m_aDialogClosedLink = rEndDialogHdl;
2650
0
    m_nError = ERRCODE_NONE;
2651
0
    if (!mpImpl->isAsyncFilePicker())
2652
0
        Application::PostUserEvent( LINK( this, FileDialogHelper, ExecuteSystemFilePicker ) );
2653
0
    else
2654
0
        mpImpl->implStartExecute();
2655
0
}
2656
2657
0
sal_Int16 FileDialogHelper::GetDialogType() const { return mpImpl ? mpImpl->m_nDialogType : 0; }
2658
2659
bool FileDialogHelper::IsPasswordEnabled() const
2660
0
{
2661
0
    return mpImpl && mpImpl->isPasswordEnabled();
2662
0
}
2663
2664
OUString FileDialogHelper::GetRealFilter() const
2665
0
{
2666
0
    OUString sFilter;
2667
0
    if (mpImpl)
2668
0
        mpImpl->getRealFilter( sFilter );
2669
0
    return sFilter;
2670
0
}
2671
2672
bool FileDialogHelper::CheckCurrentFilterOptionsCapability() const
2673
0
{
2674
0
    return mpImpl->CheckFilterOptionsCapability(mpImpl->getCurrentSfxFilter());
2675
0
}
2676
2677
void FileDialogHelper::SetTitle( const OUString& rNewTitle )
2678
0
{
2679
0
    if ( mpImpl->mxFileDlg.is() )
2680
0
        mpImpl->mxFileDlg->setTitle( rNewTitle );
2681
0
}
2682
2683
OUString FileDialogHelper::GetPath() const
2684
0
{
2685
0
    if (mpImpl->mxFileDlg)
2686
0
        if (auto aPathSeq = mpImpl->mxFileDlg->getSelectedFiles(); aPathSeq.hasElements())
2687
0
            return aPathSeq[0];
2688
2689
0
    return {};
2690
0
}
2691
2692
Sequence< OUString > FileDialogHelper::GetSelectedFiles() const
2693
0
{
2694
0
    uno::Reference<XFilePicker3> xFileDlg(mpImpl->mxFileDlg, uno::UNO_SET_THROW);
2695
0
    return xFileDlg->getSelectedFiles();
2696
0
}
2697
2698
OUString FileDialogHelper::GetDisplayDirectory() const
2699
0
{
2700
0
    return mpImpl->getPath();
2701
0
}
2702
2703
OUString FileDialogHelper::GetCurrentFilter() const
2704
0
{
2705
0
    return mpImpl->getFilter();
2706
0
}
2707
2708
ErrCode FileDialogHelper::GetGraphic( Graphic& rGraphic ) const
2709
0
{
2710
0
    return mpImpl->getGraphic( rGraphic );
2711
0
}
2712
2713
static int impl_isFolder( const OUString& rPath )
2714
0
{
2715
0
    try
2716
0
    {
2717
0
        ::ucbhelper::Content aContent(
2718
0
            rPath, uno::Reference< ucb::XCommandEnvironment > (),
2719
0
            comphelper::getProcessComponentContext() );
2720
0
        if ( aContent.isFolder() )
2721
0
            return 1;
2722
2723
0
        return 0;
2724
0
    }
2725
0
    catch ( const Exception & )
2726
0
    {
2727
0
    }
2728
2729
0
    return -1;
2730
0
}
2731
2732
void FileDialogHelper::SetDisplayDirectory( const OUString& _rPath )
2733
0
{
2734
0
    if ( _rPath.isEmpty() )
2735
0
        return;
2736
2737
    // if the given path isn't a folder, we cut off the last part
2738
    // and take it as filename and the rest of the path should be
2739
    // the folder
2740
2741
0
    INetURLObject aObj( _rPath );
2742
2743
0
    OUString sFileName = aObj.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
2744
0
    aObj.removeSegment();
2745
0
    OUString sPath = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2746
2747
0
    int nIsFolder = impl_isFolder( _rPath );
2748
0
    if ( nIsFolder == 0 ||
2749
0
         ( nIsFolder == -1 && impl_isFolder( sPath ) == 1 ) )
2750
0
    {
2751
0
        mpImpl->setFileName( sFileName );
2752
0
        mpImpl->displayFolder( sPath );
2753
0
    }
2754
0
    else
2755
0
    {
2756
0
        INetURLObject aObjPathName( _rPath );
2757
0
        OUString sFolder( aObjPathName.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2758
0
        if ( sFolder.isEmpty() )
2759
0
        {
2760
            // _rPath is not a valid path -> fallback to home directory
2761
0
            osl::Security aSecurity;
2762
0
            aSecurity.getHomeDir( sFolder );
2763
0
        }
2764
0
        mpImpl->displayFolder( sFolder );
2765
0
    }
2766
0
}
2767
2768
void FileDialogHelper::SetDisplayFolder( const OUString& _rURL )
2769
0
{
2770
0
    mpImpl->displayFolder( _rURL );
2771
0
}
2772
2773
void FileDialogHelper::SetFileName( const OUString& _rFileName )
2774
0
{
2775
0
    mpImpl->setFileName( _rFileName );
2776
0
}
2777
2778
void FileDialogHelper::AddFilter( const OUString& rFilterName,
2779
                                  const OUString& rExtension )
2780
0
{
2781
0
    mpImpl->addFilter( rFilterName, rExtension );
2782
0
}
2783
2784
void FileDialogHelper::SetCurrentFilter( const OUString& rFilter )
2785
0
{
2786
0
    OUString sFilter( rFilter );
2787
0
    if ( mpImpl->isShowFilterExtensionEnabled() )
2788
0
        sFilter = mpImpl->getFilterWithExtension( rFilter );
2789
0
    mpImpl->setFilter( sFilter );
2790
0
}
2791
2792
const uno::Reference < XFilePicker3 >& FileDialogHelper::GetFilePicker() const
2793
0
{
2794
0
    return mpImpl->mxFileDlg;
2795
0
}
2796
2797
// XFilePickerListener Methods
2798
void FileDialogHelper::FileSelectionChanged()
2799
0
{
2800
0
    mpImpl->handleFileSelectionChanged();
2801
0
}
2802
2803
void FileDialogHelper::DirectoryChanged()
2804
0
{
2805
0
    mpImpl->handleDirectoryChanged();
2806
0
}
2807
2808
OUString FileDialogHelper::HelpRequested( const FilePickerEvent& aEvent )
2809
0
{
2810
0
    return sfx2::FileDialogHelper_Impl::handleHelpRequested( aEvent );
2811
0
}
2812
2813
void FileDialogHelper::ControlStateChanged( const FilePickerEvent& aEvent )
2814
0
{
2815
0
    mpImpl->handleControlStateChanged( aEvent );
2816
0
}
2817
2818
void FileDialogHelper::DialogSizeChanged()
2819
0
{
2820
0
    mpImpl->handleDialogSizeChanged();
2821
0
}
2822
2823
void FileDialogHelper::DialogClosed( const DialogClosedEvent& _rEvent )
2824
0
{
2825
0
    m_nError = ( RET_OK == _rEvent.DialogResult ) ? ERRCODE_NONE : ERRCODE_ABORT;
2826
0
    m_aDialogClosedLink.Call( this );
2827
0
}
2828
2829
ErrCode FileOpenDialog_Impl( weld::Window* pParent,
2830
                             sal_Int16 nDialogType,
2831
                             FileDialogFlags nFlags,
2832
                             css::uno::Sequence<OUString>& rpURLList,
2833
                             OUString& rFilter,
2834
                             std::optional<SfxAllItemSet>& rpSet,
2835
                             const OUString* pPath,
2836
                             sal_Int16 nDialog,
2837
                             const css::uno::Sequence< OUString >& rDenyList,
2838
                             std::optional<bool>& rShowFilterDialog )
2839
0
{
2840
0
    ErrCode nRet;
2841
0
    std::unique_ptr<FileDialogHelper> pDialog;
2842
    // Sign existing PDF: only works with PDF files and they are opened
2843
    // read-only to discourage editing (which would invalidate existing
2844
    // signatures).
2845
0
    if (nFlags & FileDialogFlags::SignPDF)
2846
0
        pDialog.reset(new FileDialogHelper(nDialogType, nFlags, SfxResId(STR_SFX_FILTERNAME_PDF), u"pdf", u""_ustr, rDenyList, pParent));
2847
0
    else
2848
0
        pDialog.reset(new FileDialogHelper(nDialogType, nFlags, OUString(), nDialog, SfxFilterFlags::NONE, SfxFilterFlags::NONE, u""_ustr, rDenyList, pParent));
2849
2850
0
    OUString aPath;
2851
0
    if ( pPath )
2852
0
        aPath = *pPath;
2853
2854
0
    nRet = pDialog->Execute(rpURLList, rpSet, rFilter, aPath);
2855
0
    DBG_ASSERT( rFilter.indexOf(": ") == -1, "Old filter name used!");
2856
2857
0
    if (rpSet && nFlags & FileDialogFlags::SignPDF)
2858
0
        rpSet->Put(SfxBoolItem(SID_DOC_READONLY, true));
2859
2860
0
    uno::Reference< ui::dialogs::XFilePickerControlAccess > xExtFileDlg( pDialog->GetFilePicker(), uno::UNO_QUERY );
2861
0
    uno::Any aVal = xExtFileDlg->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, 0 );
2862
0
    if (aVal.has<bool>() && pDialog->CheckCurrentFilterOptionsCapability())
2863
0
        rShowFilterDialog = aVal.get<bool>();
2864
2865
0
    return nRet;
2866
0
}
2867
2868
bool IsMSType(const std::shared_ptr<const SfxFilter>& pCurrentFilter)
2869
0
{
2870
    // TODO: need a save way to distinguish MS filters from other filters
2871
    // for now MS-filters are the only alien filters that support encryption
2872
0
    return !pCurrentFilter->IsOwnFormat();
2873
0
}
2874
2875
bool IsOOXML(const std::shared_ptr<const SfxFilter>& pCurrentFilter)
2876
0
{
2877
    // For OOXML we can use the standard password ("unlimited" characters)
2878
0
    return IsMSType(pCurrentFilter) && lclSupportsOOXMLEncryption( pCurrentFilter->GetFilterName());
2879
0
}
2880
2881
ErrCode SetPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter, SfxItemSet* pSet,
2882
                    const OUString& rPasswordToOpen, std::u16string_view rPasswordToModify,
2883
                    bool bAllowPasswordReset)
2884
0
{
2885
0
    const bool bMSType = IsMSType(pCurrentFilter);
2886
0
    const bool bOOXML = IsOOXML(pCurrentFilter);
2887
2888
0
    if ( rPasswordToOpen.getLength() )
2889
0
    {
2890
0
        css::uno::Sequence< css::beans::NamedValue > aEncryptionData;
2891
2892
0
        if ( bMSType )
2893
0
        {
2894
0
            if (bOOXML)
2895
0
            {
2896
0
                ::comphelper::SequenceAsHashMap aHashData;
2897
0
                aHashData[ u"OOXPassword"_ustr ] <<= rPasswordToOpen;
2898
0
                aHashData[ u"CryptoType"_ustr ] <<= u"Standard"_ustr;
2899
0
                aEncryptionData = aHashData.getAsConstNamedValueList();
2900
0
            }
2901
0
            else
2902
0
            {
2903
0
                uno::Sequence< sal_Int8 > aUniqueID = ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 );
2904
0
                uno::Sequence< sal_Int8 > aEncryptionKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( rPasswordToOpen, aUniqueID );
2905
2906
0
                if ( aEncryptionKey.hasElements() )
2907
0
                {
2908
0
                    ::comphelper::SequenceAsHashMap aHashData;
2909
0
                    aHashData[ u"STD97EncryptionKey"_ustr ] <<= aEncryptionKey;
2910
0
                    aHashData[ u"STD97UniqueID"_ustr ] <<= aUniqueID;
2911
2912
0
                    aEncryptionData = aHashData.getAsConstNamedValueList();
2913
0
                }
2914
0
                else
2915
0
                {
2916
0
                    return ERRCODE_IO_NOTSUPPORTED;
2917
0
                }
2918
0
            }
2919
0
        }
2920
2921
        // tdf#118639: We need ODF encryption data for autorecovery where password will already
2922
        // be unavailable, even for non-ODF documents, so append it here unconditionally
2923
0
        pSet->Put(SfxUnoAnyItem(
2924
0
            SID_ENCRYPTIONDATA,
2925
0
            uno::Any(comphelper::concatSequences(
2926
0
                aEncryptionData, comphelper::OStorageHelper::CreatePackageEncryptionData(
2927
0
                                    rPasswordToOpen)))));
2928
0
    }
2929
0
    else if (bAllowPasswordReset)
2930
0
    {
2931
        // Remove password
2932
2933
0
        if (pSet->HasItem(SID_ENCRYPTIONDATA))
2934
0
            pSet->ClearItem(SID_MODIFYPASSWORDINFO);
2935
0
        if (pSet->HasItem(SID_ENCRYPTIONDATA))
2936
0
            pSet->ClearItem(SID_ENCRYPTIONDATA);
2937
2938
0
        return ERRCODE_NONE;
2939
0
    }
2940
2941
0
    if ( bMSType )
2942
0
    {
2943
0
        if (bOOXML)
2944
0
        {
2945
0
            uno::Sequence<beans::PropertyValue> aModifyPasswordInfo
2946
0
                = ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfoOOXML(
2947
0
                    rPasswordToModify);
2948
0
            if (aModifyPasswordInfo.hasElements() && pSet)
2949
0
                pSet->Put(
2950
0
                    SfxUnoAnyItem(SID_MODIFYPASSWORDINFO, uno::Any(aModifyPasswordInfo)));
2951
0
        }
2952
0
        else
2953
0
        {
2954
            // the empty password has 0 as Hash
2955
0
            sal_Int32 nHash = SfxMedium::CreatePasswordToModifyHash(
2956
0
                rPasswordToModify,
2957
0
                pCurrentFilter->GetServiceName() == "com.sun.star.text.TextDocument");
2958
0
            if (nHash && pSet)
2959
0
                pSet->Put(SfxUnoAnyItem(SID_MODIFYPASSWORDINFO, uno::Any(nHash)));
2960
0
        }
2961
0
    }
2962
0
    else
2963
0
    {
2964
0
        uno::Sequence< beans::PropertyValue > aModifyPasswordInfo = ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( rPasswordToModify );
2965
0
        if ( aModifyPasswordInfo.hasElements() && pSet)
2966
0
            pSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::Any( aModifyPasswordInfo ) ) );
2967
0
    }
2968
0
    return ERRCODE_NONE;
2969
0
}
2970
2971
2972
2973
ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter, OUString const & aURL, SfxItemSet* pSet, const css::uno::Reference<css::awt::XWindow>& rParent)
2974
0
{
2975
0
    uno::Reference<task::XInteractionHandler2> xInteractionHandler = task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), rParent);
2976
0
    const auto eType = IsMSType(pCurrentFilter) && !IsOOXML(pCurrentFilter) ?
2977
0
        ::comphelper::DocPasswordRequestType::MS :
2978
0
        ::comphelper::DocPasswordRequestType::Standard;
2979
2980
0
    ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest( new ::comphelper::DocPasswordRequest( eType, css::task::PasswordRequestMode_PASSWORD_CREATE, aURL, bool( pCurrentFilter->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY ) ) );
2981
2982
0
    const bool bMSType = IsMSType(pCurrentFilter);
2983
2984
0
    do
2985
0
    {
2986
0
        xInteractionHandler->handle( uno::Reference< css::task::XInteractionRequest >( pPasswordRequest ) );
2987
0
        if (!pPasswordRequest->isPassword() || bMSType)
2988
0
        {
2989
0
            break;
2990
0
        }
2991
0
        OString const utf8Pwd(OUStringToOString(pPasswordRequest->getPassword(), RTL_TEXTENCODING_UTF8));
2992
0
        OString const utf8Ptm(OUStringToOString(pPasswordRequest->getPasswordToModify(), RTL_TEXTENCODING_UTF8));
2993
0
        if (!(52 <= utf8Pwd.getLength() && utf8Pwd.getLength() <= 55
2994
0
                && GetODFSaneDefaultVersion() < SvtSaveOptions::ODFSVER_012)
2995
0
            && (52 > utf8Ptm.getLength() || utf8Ptm.getLength() > 55))
2996
0
        {
2997
0
            break;
2998
0
        }
2999
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(Application::GetFrameWeld(rParent), VclMessageType::Warning,
3000
0
            VclButtonsType::Ok, SfxResId(STR_PASSWORD_LEN)));
3001
0
        xBox->set_secondary_text(SfxResId(STR_PASSWORD_WARNING));
3002
0
        xBox->run();
3003
0
    }
3004
0
    while (true);
3005
0
    if ( !pPasswordRequest->isPassword() )
3006
0
        return ERRCODE_ABORT;
3007
3008
0
    const auto result = SetPassword(pCurrentFilter, pSet, pPasswordRequest->getPassword(), pPasswordRequest->getPasswordToModify());
3009
3010
0
    if ( result != ERRCODE_IO_NOTSUPPORTED && pPasswordRequest->getRecommendReadOnly() )
3011
0
        pSet->Put( SfxBoolItem( SID_RECOMMENDREADONLY, true ) );
3012
3013
0
    return result;
3014
0
}
3015
3016
OUString EncodeSpaces_Impl( const OUString& rSource )
3017
0
{
3018
0
    OUString sRet = rSource.replaceAll( " ", "%20" );
3019
0
    return sRet;
3020
0
}
3021
3022
OUString DecodeSpaces_Impl( const OUString& rSource )
3023
0
{
3024
0
    OUString sRet = rSource.replaceAll( "%20", " " );
3025
0
    return sRet;
3026
0
}
3027
3028
}   // end of namespace sfx2
3029
3030
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */