1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <string_view>
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/XFilterManager.hpp>
38 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
39 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
40 #include <com/sun/star/lang/XServiceInfo.hpp>
41 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/beans/PropertyValue.hpp>
44 #include <com/sun/star/beans/NamedValue.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/embed/ElementModes.hpp>
47 #include <com/sun/star/container/XEnumeration.hpp>
48 #include <com/sun/star/container/XContainerQuery.hpp>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include <com/sun/star/container/XNameContainer.hpp>
51 #include <com/sun/star/task/InteractionHandler.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/urlobj.hxx>
60 #include <vcl/help.hxx>
61 #include <vcl/weld.hxx>
62 #include <unotools/ucbstreamhelper.hxx>
63 #include <unotools/ucbhelper.hxx>
64 #include <osl/file.hxx>
65 #include <osl/security.hxx>
66 #include <vcl/mnemonic.hxx>
67 #include <vcl/svapp.hxx>
68 #include <unotools/pathoptions.hxx>
69 #include <unotools/saveopt.hxx>
70 #include <unotools/securityoptions.hxx>
71 #include <svl/itemset.hxx>
72 #include <svl/eitem.hxx>
73 #include <svl/intitem.hxx>
74 #include <vcl/dibtools.hxx>
75 #include <vcl/graphicfilter.hxx>
76 #include <unotools/viewoptions.hxx>
77 #include <svtools/helpids.h>
78 #include <comphelper/docpasswordrequest.hxx>
79 #include <comphelper/docpasswordhelper.hxx>
80 #include <ucbhelper/content.hxx>
81 #include <comphelper/storagehelper.hxx>
82 #include <sfx2/app.hxx>
83 #include <sfx2/frame.hxx>
84 #include <sfx2/docfile.hxx>
85 #include <sfx2/docfilt.hxx>
86 #include <sfx2/objsh.hxx>
87 #include <sfx2/sfxresid.hxx>
88 #include <sfx2/sfxsids.hrc>
89 #include "filtergrouping.hxx"
90 #include "filedlgimpl.hxx"
91 #include <sfx2/strings.hrc>
92 #include <sal/log.hxx>
93 #include <comphelper/sequence.hxx>
94 #include <tools/diagnose_ex.h>
95 #include <officecfg/Office/Common.hxx>
102 using namespace ::com::sun::star
;
103 using namespace ::com::sun::star::container
;
104 using namespace ::com::sun::star::lang
;
105 using namespace ::com::sun::star::ui::dialogs
;
106 using namespace ::com::sun::star::ui::dialogs::TemplateDescription
;
107 using namespace ::com::sun::star::uno
;
108 using namespace ::com::sun::star::beans
;
109 using namespace ::cppu
;
111 constexpr OUStringLiteral IODLG_CONFIGNAME
= u
"FilePicker_Save";
112 constexpr OUStringLiteral IMPGRF_CONFIGNAME
= u
"FilePicker_Graph";
113 constexpr OUStringLiteral USERITEM_NAME
= u
"UserItem";
120 bool lclSupportsOOXMLEncryption(std::u16string_view aFilterName
)
122 return aFilterName
== u
"Calc MS Excel 2007 XML"
123 || aFilterName
== u
"MS Word 2007 XML"
124 || aFilterName
== u
"Impress MS PowerPoint 2007 XML"
125 || aFilterName
== u
"Impress MS PowerPoint 2007 XML AutoPlay"
126 || aFilterName
== u
"Calc Office Open XML"
127 || aFilterName
== u
"Impress Office Open XML"
128 || aFilterName
== u
"Impress Office Open XML AutoPlay"
129 || aFilterName
== u
"Office Open XML Text";
133 static std::optional
<OUString
> GetLastFilterConfigId( FileDialogHelper::Context _eContext
)
135 static constexpr OUStringLiteral
aSD_EXPORT_IDENTIFIER(u
"SdExportLastFilter");
136 static constexpr OUStringLiteral
aSI_EXPORT_IDENTIFIER(u
"SiExportLastFilter");
137 static constexpr OUStringLiteral
aSW_EXPORT_IDENTIFIER(u
"SwExportLastFilter");
141 case FileDialogHelper::DrawExport
: return aSD_EXPORT_IDENTIFIER
;
142 case FileDialogHelper::ImpressExport
: return aSI_EXPORT_IDENTIFIER
;
143 case FileDialogHelper::WriterExport
: return aSW_EXPORT_IDENTIFIER
;
150 static OUString
EncodeSpaces_Impl( const OUString
& rSource
);
151 static OUString
DecodeSpaces_Impl( const OUString
& rSource
);
153 // FileDialogHelper_Impl
155 // XFilePickerListener Methods
156 void SAL_CALL
FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent
& )
158 SolarMutexGuard aGuard
;
159 mpAntiImpl
->FileSelectionChanged();
162 void SAL_CALL
FileDialogHelper_Impl::directoryChanged( const FilePickerEvent
& )
164 SolarMutexGuard aGuard
;
165 mpAntiImpl
->DirectoryChanged();
168 OUString SAL_CALL
FileDialogHelper_Impl::helpRequested( const FilePickerEvent
& aEvent
)
170 SolarMutexGuard aGuard
;
171 return sfx2::FileDialogHelper::HelpRequested( aEvent
);
174 void SAL_CALL
FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent
& aEvent
)
176 SolarMutexGuard aGuard
;
177 mpAntiImpl
->ControlStateChanged( aEvent
);
180 void SAL_CALL
FileDialogHelper_Impl::dialogSizeChanged()
182 SolarMutexGuard aGuard
;
183 mpAntiImpl
->DialogSizeChanged();
186 // XDialogClosedListener Methods
187 void SAL_CALL
FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent
& _rEvent
)
189 SolarMutexGuard aGuard
;
190 mpAntiImpl
->DialogClosed( _rEvent
);
191 postExecute( _rEvent
.DialogResult
);
194 // handle XFilePickerListener events
195 void FileDialogHelper_Impl::handleFileSelectionChanged()
201 maPreviewIdle
.Start();
204 void FileDialogHelper_Impl::handleDirectoryChanged()
207 TimeOutHdl_Impl( nullptr );
210 OUString
FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent
& aEvent
)
212 //!!! todo: cache the help strings (here or TRA)
215 // mapping from element id -> help id
216 switch ( aEvent
.ElementId
)
218 case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
:
219 sHelpId
= HID_FILESAVE_AUTOEXTENSION
;
222 case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
223 sHelpId
= HID_FILESAVE_SAVEWITHPASSWORD
;
226 case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
227 sHelpId
= HID_FILESAVE_CUSTOMIZEFILTER
;
230 case ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
231 sHelpId
= HID_FILEOPEN_READONLY
;
234 case ExtendedFilePickerElementIds::CHECKBOX_LINK
:
235 sHelpId
= HID_FILEDLG_LINK_CB
;
238 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
239 sHelpId
= HID_FILEDLG_PREVIEW_CB
;
242 case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
:
243 sHelpId
= HID_FILESAVE_DOPLAY
;
246 case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL
:
247 case ExtendedFilePickerElementIds::LISTBOX_VERSION
:
248 sHelpId
= HID_FILEOPEN_VERSION
;
251 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL
:
252 case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
:
253 sHelpId
= HID_FILESAVE_TEMPLATE
;
256 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL
:
257 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
:
258 sHelpId
= HID_FILEOPEN_IMAGE_TEMPLATE
;
261 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR_LABEL
:
262 case ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR
:
263 sHelpId
= HID_FILEOPEN_IMAGE_ANCHOR
;
266 case ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
267 sHelpId
= HID_FILESAVE_SELECTION
;
271 SAL_WARN( "sfx.dialog", "invalid element id" );
275 Help
* pHelp
= Application::GetHelp();
277 aHelpText
= pHelp
->GetHelpText(OStringToOUString(sHelpId
, RTL_TEXTENCODING_UTF8
), static_cast<weld::Widget
*>(nullptr));
281 void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent
& aEvent
)
283 switch ( aEvent
.ElementId
)
285 case CommonFilePickerElementIds::LISTBOX_FILTER
:
286 updateFilterOptionsBox();
287 enablePasswordBox( false );
288 updateSelectionBox();
289 // only use it for export and with our own dialog
290 if ( mbExport
&& !mbSystemPicker
)
291 updateExportButton();
294 case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
:
295 updatePreviewState(true);
300 void FileDialogHelper_Impl::handleDialogSizeChanged()
303 TimeOutHdl_Impl( nullptr );
306 // XEventListener Methods
307 void SAL_CALL
FileDialogHelper_Impl::disposing( const EventObject
& )
309 SolarMutexGuard aGuard
;
313 void FileDialogHelper_Impl::dispose()
315 if ( mxFileDlg
.is() )
317 // remove the event listener
318 mxFileDlg
->removeFilePickerListener( this );
320 ::comphelper::disposeComponent( mxFileDlg
);
325 OUString
FileDialogHelper_Impl::getCurrentFilterUIName() const
327 OUString aFilterName
;
331 aFilterName
= mxFileDlg
->getCurrentFilter();
333 if ( !aFilterName
.isEmpty() && isShowFilterExtensionEnabled() )
334 aFilterName
= getFilterName( aFilterName
);
340 void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString
& _rContextIdentifier
)
342 SvtViewOptions
aDlgOpt( EViewType::Dialog
, IODLG_CONFIGNAME
);
344 if( aDlgOpt
.Exists() )
346 OUString aLastFilter
;
347 if( aDlgOpt
.GetUserItem( _rContextIdentifier
) >>= aLastFilter
)
348 setFilter( aLastFilter
);
352 void FileDialogHelper_Impl::SaveLastUsedFilter()
354 std::optional
<OUString
> pConfigId
= GetLastFilterConfigId( meContext
);
356 SvtViewOptions( EViewType::Dialog
, IODLG_CONFIGNAME
).SetUserItem( *pConfigId
,
357 makeAny( getFilterWithExtension( getFilter() ) ) );
360 std::shared_ptr
<const SfxFilter
> FileDialogHelper_Impl::getCurentSfxFilter()
362 OUString aFilterName
= getCurrentFilterUIName();
364 if ( mpMatcher
&& !aFilterName
.isEmpty() )
365 return mpMatcher
->GetFilter4UIName( aFilterName
, m_nMustFlags
, m_nDontFlags
);
370 bool FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId
, bool _bEnable
)
372 bool bIsEnabled
= false;
374 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
375 if ( xCtrlAccess
.is() )
379 xCtrlAccess
->enableControl( _nExtendedControlId
, _bEnable
);
380 bIsEnabled
= _bEnable
;
382 catch( const IllegalArgumentException
& )
384 TOOLS_WARN_EXCEPTION( "sfx", "FileDialogHelper_Impl::updateExtendedControl" );
390 bool FileDialogHelper_Impl::CheckFilterOptionsCapability( const std::shared_ptr
<const SfxFilter
>& _pFilter
)
392 bool bResult
= false;
394 if( mxFilterCFG
.is() && _pFilter
)
398 Sequence
< PropertyValue
> aProps
;
399 Any aAny
= mxFilterCFG
->getByName( _pFilter
->GetName() );
400 if ( aAny
>>= aProps
)
402 OUString aServiceName
;
403 for( const auto& rProp
: std::as_const(aProps
) )
405 if( rProp
.Name
== "UIComponent" )
407 rProp
.Value
>>= aServiceName
;
408 if( !aServiceName
.isEmpty() )
414 catch( const Exception
& )
422 bool FileDialogHelper_Impl::isInOpenMode() const
426 switch ( m_nDialogType
)
428 case FILEOPEN_SIMPLE
:
429 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
431 case FILEOPEN_LINK_PLAY
:
432 case FILEOPEN_READONLY_VERSION
:
433 case FILEOPEN_LINK_PREVIEW
:
434 case FILEOPEN_PREVIEW
:
441 void FileDialogHelper_Impl::updateFilterOptionsBox()
443 if ( !m_bHaveFilterOptions
)
446 updateExtendedControl(
447 ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
,
448 CheckFilterOptionsCapability( getCurentSfxFilter() )
452 void FileDialogHelper_Impl::updateExportButton()
454 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
455 if ( !xCtrlAccess
.is() )
458 OUString
sOldLabel( xCtrlAccess
->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
) );
460 // initialize button label; we need the label with the mnemonic char
461 if ( maButtonLabel
.isEmpty() || maButtonLabel
.indexOf( MNEMONIC_CHAR
) == -1 )
463 // cut the ellipses, if necessary
464 sal_Int32 nIndex
= sOldLabel
.indexOf( "..." );
466 nIndex
= sOldLabel
.getLength();
467 maButtonLabel
= sOldLabel
.copy( 0, nIndex
);
470 OUString sLabel
= maButtonLabel
;
471 // filter with options -> append ellipses on export button label
472 if ( CheckFilterOptionsCapability( getCurentSfxFilter() ) )
475 if ( sOldLabel
!= sLabel
)
479 xCtrlAccess
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
, sLabel
);
481 catch( const IllegalArgumentException
& )
483 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::updateExportButton" );
488 void FileDialogHelper_Impl::updateSelectionBox()
490 if ( !mbHasSelectionBox
)
493 // Does the selection box exist?
494 bool bSelectionBoxFound
= false;
495 uno::Reference
< XControlInformation
> xCtrlInfo( mxFileDlg
, UNO_QUERY
);
496 if ( xCtrlInfo
.is() )
498 Sequence
< OUString
> aCtrlList
= xCtrlInfo
->getSupportedControls();
499 bSelectionBoxFound
= comphelper::findValue(aCtrlList
, "SelectionBox") != -1;
502 if ( bSelectionBoxFound
)
504 std::shared_ptr
<const SfxFilter
> pFilter
= getCurentSfxFilter();
505 mbSelectionFltrEnabled
= updateExtendedControl(
506 ExtendedFilePickerElementIds::CHECKBOX_SELECTION
,
507 ( mbSelectionEnabled
&& pFilter
&& ( pFilter
->GetFilterFlags() & SfxFilterFlags::SUPPORTSSELECTION
) ) );
508 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
509 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, makeAny( mbSelection
) );
513 void FileDialogHelper_Impl::enablePasswordBox( bool bInit
)
515 if ( ! mbHasPassword
)
518 bool bWasEnabled
= mbIsPwdEnabled
;
520 std::shared_ptr
<const SfxFilter
> pCurrentFilter
= getCurentSfxFilter();
521 mbIsPwdEnabled
= updateExtendedControl(
522 ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
,
523 pCurrentFilter
&& ( pCurrentFilter
->GetFilterFlags() & SfxFilterFlags::ENCRYPTION
)
528 // in case of initialization previous state is not interesting
531 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
532 if( mbPwdCheckBoxState
)
533 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( true ) );
536 else if( !bWasEnabled
&& mbIsPwdEnabled
)
538 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
539 if( mbPwdCheckBoxState
)
540 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( true ) );
542 else if( bWasEnabled
&& !mbIsPwdEnabled
)
544 // remember user settings until checkbox is enabled
545 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
546 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
547 bool bPassWord
= false;
548 mbPwdCheckBoxState
= ( aValue
>>= bPassWord
) && bPassWord
;
549 xCtrlAccess
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0, makeAny( false ) );
553 void FileDialogHelper_Impl::updatePreviewState( bool _bUpdatePreviewWindow
)
558 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
560 // check, whether or not we have to display a preview
561 if ( !xCtrlAccess
.is() )
566 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
567 bool bShowPreview
= false;
569 if ( aValue
>>= bShowPreview
)
571 mbShowPreview
= bShowPreview
;
573 // setShowState has currently no effect for the
574 // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx)
575 uno::Reference
< XFilePreview
> xFilePreview( mxFileDlg
, UNO_QUERY
);
576 if ( xFilePreview
.is() )
577 xFilePreview
->setShowState( mbShowPreview
);
579 if ( _bUpdatePreviewWindow
)
580 TimeOutHdl_Impl( nullptr );
583 catch( const Exception
& )
585 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::updatePreviewState" );
589 void FileDialogHelper_Impl::updateVersions()
591 Sequence
< OUString
> aEntries
;
592 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
594 if ( aPathSeq
.getLength() == 1 )
596 INetURLObject
aObj( aPathSeq
[0] );
598 if ( ( aObj
.GetProtocol() == INetProtocol::File
) &&
599 ( utl::UCBContentHelper::IsDocument( aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) ) ) )
603 uno::Reference
< embed::XStorage
> xStorage
= ::comphelper::OStorageHelper::GetStorageFromURL(
604 aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
),
605 embed::ElementModes::READ
);
607 DBG_ASSERT( xStorage
.is(), "The method must return the storage or throw exception!" );
608 if ( !xStorage
.is() )
609 throw uno::RuntimeException();
611 const uno::Sequence
< util::RevisionTag
> xVersions
= SfxMedium::GetVersionList( xStorage
);
613 aEntries
.realloc( xVersions
.getLength() + 1 );
614 aEntries
.getArray()[0] = SfxResId( STR_SFX_FILEDLG_ACTUALVERSION
);
616 std::transform(xVersions
.begin(), xVersions
.end(), std::next(aEntries
.getArray()),
617 [](const util::RevisionTag
& rVersion
) -> OUString
{ return rVersion
.Identifier
; });
619 catch( const uno::Exception
& )
625 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
630 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
631 ControlActions::DELETE_ITEMS
, aValue
);
633 catch( const IllegalArgumentException
& ){}
635 if ( !aEntries
.hasElements() )
641 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
642 ControlActions::ADD_ITEMS
, aValue
);
645 aPos
<<= sal_Int32(0);
646 xDlg
->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
647 ControlActions::SET_SELECT_ITEM
, aPos
);
649 catch( const IllegalArgumentException
& ){}
652 IMPL_LINK_NOARG(FileDialogHelper_Impl
, TimeOutHdl_Impl
, Timer
*, void)
660 uno::Reference
< XFilePreview
> xFilePicker( mxFileDlg
, UNO_QUERY
);
662 if ( ! xFilePicker
.is() )
665 Sequence
< OUString
> aPathSeq
= mxFileDlg
->getFiles();
667 if ( mbShowPreview
&& ( aPathSeq
.getLength() == 1 ) )
669 OUString aURL
= aPathSeq
[0];
671 if ( ERRCODE_NONE
== getGraphic( aURL
, maGraphic
) )
673 // changed the code slightly;
674 // before: the bitmap was scaled and
675 // surrounded a white frame
676 // now: the bitmap will only be scaled
677 // and the filepicker implementation
678 // is responsible for placing it at its
679 // proper position and painting a frame
681 BitmapEx aBmp
= maGraphic
.GetBitmapEx();
682 if ( !aBmp
.IsEmpty() )
684 // scale the bitmap to the correct size
685 sal_Int32 nOutWidth
= xFilePicker
->getAvailableWidth();
686 sal_Int32 nOutHeight
= xFilePicker
->getAvailableHeight();
687 sal_Int32 nBmpWidth
= aBmp
.GetSizePixel().Width();
688 sal_Int32 nBmpHeight
= aBmp
.GetSizePixel().Height();
690 double nXRatio
= static_cast<double>(nOutWidth
) / nBmpWidth
;
691 double nYRatio
= static_cast<double>(nOutHeight
) / nBmpHeight
;
693 if ( nXRatio
< nYRatio
)
694 aBmp
.Scale( nXRatio
, nXRatio
);
696 aBmp
.Scale( nYRatio
, nYRatio
);
698 // Convert to true color, to allow CopyPixel
699 aBmp
.Convert( BmpConversion::N24Bit
);
701 // and copy it into the Any
702 SvMemoryStream aData
;
704 WriteDIB(aBmp
, aData
, false);
706 const Sequence
< sal_Int8
> aBuffer(
707 static_cast< const sal_Int8
* >(aData
.GetData()),
708 aData
.GetEndOfData() );
717 SolarMutexReleaser aReleaseForCallback
;
718 // clear the preview window
719 xFilePicker
->setImage( FilePreviewImageFormats::BITMAP
, aAny
);
721 catch( const IllegalArgumentException
& )
726 ErrCode
FileDialogHelper_Impl::getGraphic( const OUString
& rURL
,
727 Graphic
& rGraphic
) const
729 if ( utl::UCBContentHelper::IsFolder( rURL
) )
730 return ERRCODE_IO_NOTAFILE
;
732 if ( !mpGraphicFilter
)
733 return ERRCODE_IO_NOTSUPPORTED
;
735 // select graphic filter from dialog filter selection
736 OUString
aCurFilter( getFilter() );
738 sal_uInt16 nFilter
= !aCurFilter
.isEmpty() && mpGraphicFilter
->GetImportFormatCount()
739 ? mpGraphicFilter
->GetImportFormatNumber( aCurFilter
)
740 : GRFILTER_FORMAT_DONTKNOW
;
742 INetURLObject
aURLObj( rURL
);
744 if ( aURLObj
.HasError() || INetProtocol::NotValid
== aURLObj
.GetProtocol() )
746 aURLObj
.SetSmartProtocol( INetProtocol::File
);
747 aURLObj
.SetSmartURL( rURL
);
750 ErrCode nRet
= ERRCODE_NONE
;
752 GraphicFilterImportFlags nFilterImportFlags
= GraphicFilterImportFlags::SetLogsizeForJpeg
;
754 if ( INetProtocol::File
!= aURLObj
.GetProtocol() )
756 std::unique_ptr
<SvStream
> pStream
= ::utl::UcbStreamHelper::CreateStream( rURL
, StreamMode::READ
);
759 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, rURL
, *pStream
, nFilter
, nullptr, nFilterImportFlags
);
761 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, nullptr, nFilterImportFlags
);
765 nRet
= mpGraphicFilter
->ImportGraphic( rGraphic
, aURLObj
, nFilter
, nullptr, nFilterImportFlags
);
771 ErrCode
FileDialogHelper_Impl::getGraphic( Graphic
& rGraphic
) const
773 ErrCode nRet
= ERRCODE_NONE
;
775 // rhbz#1079672 do not return maGraphic, it needs not to be the selected file
778 Sequence
<OUString
> aPathSeq
= mxFileDlg
->getFiles();
780 if (aPathSeq
.getLength() == 1)
785 if (!aPath
.isEmpty())
786 nRet
= getGraphic(aPath
, rGraphic
);
788 nRet
= ERRCODE_IO_GENERAL
;
793 static bool lcl_isSystemFilePicker( const uno::Reference
< XExecutableDialog
>& _rxFP
)
797 uno::Reference
< XServiceInfo
> xSI( _rxFP
, UNO_QUERY
);
800 return xSI
->supportsService( "com.sun.star.ui.dialogs.SystemFilePicker" );
802 catch( const Exception
& )
810 bool lcl_isAsyncFilePicker( const uno::Reference
< XExecutableDialog
>& _rxFP
)
814 uno::Reference
<XAsynchronousExecutableDialog
> xSI(_rxFP
, UNO_QUERY
);
817 catch( const Exception
& )
823 enum open_or_save_t
{OPEN
, SAVE
, UNDEFINED
};
827 static open_or_save_t
lcl_OpenOrSave(sal_Int16
const nDialogType
)
831 case FILEOPEN_SIMPLE
:
832 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
833 case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR
:
835 case FILEOPEN_LINK_PLAY
:
836 case FILEOPEN_READONLY_VERSION
:
837 case FILEOPEN_LINK_PREVIEW
:
838 case FILEOPEN_PREVIEW
:
840 case FILESAVE_SIMPLE
:
841 case FILESAVE_AUTOEXTENSION_PASSWORD
:
842 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
843 case FILESAVE_AUTOEXTENSION_SELECTION
:
844 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
845 case FILESAVE_AUTOEXTENSION
:
848 assert(false); // invalid dialog type
853 // FileDialogHelper_Impl
855 css::uno::Reference
<css::awt::XWindow
> FileDialogHelper_Impl::GetFrameInterface()
858 return mpFrameWeld
->GetXWindow();
859 return css::uno::Reference
<css::awt::XWindow
>();
862 FileDialogHelper_Impl::FileDialogHelper_Impl(
863 FileDialogHelper
* _pAntiImpl
,
864 sal_Int16 nDialogType
,
865 FileDialogFlags nFlags
,
867 weld::Window
* pFrameWeld
,
868 const OUString
& sStandardDir
,
869 const css::uno::Sequence
< OUString
>& rDenyList
871 :maPreviewIdle("sfx2 FileDialogHelper_Impl maPreviewIdle")
872 ,m_nDialogType ( nDialogType
)
873 ,meContext ( FileDialogHelper::UnknownContext
)
875 const char* pServiceName
=nullptr;
878 case SFX2_IMPL_DIALOG_SYSTEM
:
879 case SFX2_IMPL_DIALOG_OOO
:
880 pServiceName
= "com.sun.star.ui.dialogs.OfficeFilePicker";
882 case SFX2_IMPL_DIALOG_REMOTE
:
883 pServiceName
= "com.sun.star.ui.dialogs.RemoteFilePicker";
886 pServiceName
= "com.sun.star.ui.dialogs.FilePicker";
890 OUString aService
= OUString::createFromAscii( pServiceName
);
892 uno::Reference
< XMultiServiceFactory
> xFactory( ::comphelper::getProcessServiceFactory() );
894 // create the file open dialog
895 // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION
897 mpFrameWeld
= pFrameWeld
;
898 mpAntiImpl
= _pAntiImpl
;
899 mbHasAutoExt
= false;
900 mbHasPassword
= false;
901 m_bHaveFilterOptions
= false;
902 mbIsPwdEnabled
= true;
903 mbHasVersions
= false;
904 mbHasPreview
= false;
905 mbShowPreview
= false;
906 mbDeleteMatcher
= false;
907 mbInsert
= bool(nFlags
& (FileDialogFlags::Insert
|
908 FileDialogFlags::InsertCompare
|
909 FileDialogFlags::InsertMerge
));
910 mbExport
= bool(nFlags
& FileDialogFlags::Export
);
912 mbPwdCheckBoxState
= false;
914 mbSelectionEnabled
= true;
915 mbHasSelectionBox
= false;
916 mbSelectionFltrEnabled
= false;
919 m_nDontFlags
= SFX_FILTER_NOTINSTALLED
| SfxFilterFlags::INTERNAL
| SfxFilterFlags::NOTINFILEDLG
;
920 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
921 m_nMustFlags
= SfxFilterFlags::IMPORT
;
923 m_nMustFlags
= SfxFilterFlags::EXPORT
;
927 mpGraphicFilter
= nullptr;
928 mnPostUserEventId
= nullptr;
930 // create the picker component
931 mxFileDlg
.set(xFactory
->createInstance( aService
), css::uno::UNO_QUERY
);
932 mbSystemPicker
= lcl_isSystemFilePicker( mxFileDlg
);
933 mbAsyncPicker
= lcl_isAsyncFilePicker(mxFileDlg
);
935 uno::Reference
< XInitialization
> xInit( mxFileDlg
, UNO_QUERY
);
937 if ( ! mxFileDlg
.is() )
945 sal_Int16 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
947 switch ( m_nDialogType
)
949 case FILEOPEN_SIMPLE
:
950 nTemplateDescription
= TemplateDescription::FILEOPEN_SIMPLE
;
953 case FILESAVE_SIMPLE
:
954 nTemplateDescription
= TemplateDescription::FILESAVE_SIMPLE
;
958 case FILESAVE_AUTOEXTENSION_PASSWORD
:
959 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
;
960 mbHasPassword
= true;
965 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
966 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
;
967 mbHasPassword
= true;
969 m_bHaveFilterOptions
= true;
973 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
981 case FILESAVE_AUTOEXTENSION_SELECTION
:
982 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
;
985 mbHasSelectionBox
= true;
986 if ( mbExport
&& !mxFilterCFG
.is() && xFactory
.is() )
989 xFactory
->createInstance( "com.sun.star.document.FilterFactory" ),
994 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
995 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
;
1000 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
1001 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
;
1002 mbHasPreview
= true;
1005 case FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR
:
1006 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR
;
1007 mbHasPreview
= true;
1011 nTemplateDescription
= TemplateDescription::FILEOPEN_PLAY
;
1014 case FILEOPEN_LINK_PLAY
:
1015 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PLAY
;
1018 case FILEOPEN_READONLY_VERSION
:
1019 nTemplateDescription
= TemplateDescription::FILEOPEN_READONLY_VERSION
;
1020 mbHasVersions
= true;
1023 case FILEOPEN_LINK_PREVIEW
:
1024 nTemplateDescription
= TemplateDescription::FILEOPEN_LINK_PREVIEW
;
1025 mbHasPreview
= true;
1028 case FILESAVE_AUTOEXTENSION
:
1029 nTemplateDescription
= TemplateDescription::FILESAVE_AUTOEXTENSION
;
1030 mbHasAutoExt
= true;
1034 case FILEOPEN_PREVIEW
:
1035 nTemplateDescription
= TemplateDescription::FILEOPEN_PREVIEW
;
1036 mbHasPreview
= true;
1040 SAL_WARN( "sfx.dialog", "FileDialogHelper::ctor with unknown type" );
1046 maPreviewIdle
.SetPriority( TaskPriority::LOWEST
);
1047 maPreviewIdle
.SetInvokeHandler( LINK( this, FileDialogHelper_Impl
, TimeOutHdl_Impl
) );
1050 auto xWindow
= GetFrameInterface();
1052 Sequence
< Any
> aInitArguments(!xWindow
.is() ? 3 : 4);
1053 auto pInitArguments
= aInitArguments
.getArray();
1055 // This is a hack. We currently know that the internal file picker implementation
1056 // supports the extended arguments as specified below.
1058 // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args
1059 // b) adjust the implementation of the system file picker to that it recognizes it
1060 if ( mbSystemPicker
)
1062 pInitArguments
[0] <<= nTemplateDescription
;
1064 pInitArguments
[1] <<= xWindow
;
1068 pInitArguments
[0] <<= NamedValue(
1069 "TemplateDescription",
1070 makeAny( nTemplateDescription
)
1073 pInitArguments
[1] <<= NamedValue(
1075 makeAny( sStandardDir
)
1078 pInitArguments
[2] <<= NamedValue(
1080 makeAny( rDenyList
)
1085 pInitArguments
[3] <<= NamedValue("ParentWindow", makeAny(xWindow
));
1090 xInit
->initialize( aInitArguments
);
1092 catch( const Exception
& )
1094 OSL_FAIL( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" );
1099 // set multiselection mode
1100 if ( nFlags
& FileDialogFlags::MultiSelection
)
1101 mxFileDlg
->setMultiSelectionMode( true );
1103 if ( nFlags
& FileDialogFlags::Graphic
) // generate graphic filter only on demand
1111 mxFileDlg
->setTitle( SfxResId( STR_SFX_EXPLORERFILE_EXPORT
) );
1113 css::uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY_THROW
);
1114 xCtrlAccess
->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR
, true );
1116 catch( const Exception
& ) { }
1119 // Save a copy dialog
1120 if ( nFlags
& FileDialogFlags::SaveACopy
)
1122 mxFileDlg
->setTitle( SfxResId( STR_PB_SAVEACOPY
) );
1125 // the "insert file" dialog needs another title
1128 if ( nFlags
& FileDialogFlags::InsertCompare
)
1130 mxFileDlg
->setTitle( SfxResId( STR_PB_COMPAREDOC
) );
1132 else if ( nFlags
& FileDialogFlags::InsertMerge
)
1134 mxFileDlg
->setTitle( SfxResId( STR_PB_MERGEDOC
) );
1138 mxFileDlg
->setTitle( SfxResId( STR_SFX_EXPLORERFILE_INSERT
) );
1140 uno::Reference
< XFilePickerControlAccess
> xExtDlg( mxFileDlg
, UNO_QUERY
);
1145 xExtDlg
->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK
,
1146 SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT
) );
1148 catch( const IllegalArgumentException
& ){}
1152 // add the event listener
1153 mxFileDlg
->addFilePickerListener( this );
1156 css::uno::Reference
<css::ui::dialogs::XFolderPicker2
> createFolderPicker(const css::uno::Reference
<css::uno::XComponentContext
>& rContext
, weld::Window
* pPreferredParent
)
1158 auto xRet
= css::ui::dialogs::FolderPicker::create(rContext
);
1160 // see FileDialogHelper_Impl::FileDialogHelper_Impl (above) for args to FilePicker
1161 // reuse the same arguments for FolderPicker
1162 if (pPreferredParent
&& lcl_isSystemFilePicker(xRet
))
1164 uno::Reference
< XInitialization
> xInit(xRet
, UNO_QUERY
);
1167 Sequence
<Any
> aInitArguments
{ Any(sal_Int32(0)), Any(pPreferredParent
->GetXWindow()) };
1171 xInit
->initialize(aInitArguments
);
1173 catch (const Exception
&)
1175 OSL_FAIL( "createFolderPicker: could not initialize the picker!" );
1183 FileDialogHelper_Impl::~FileDialogHelper_Impl()
1185 // Remove user event if we haven't received it yet
1186 if ( mnPostUserEventId
)
1187 Application::RemoveUserEvent( mnPostUserEventId
);
1188 mnPostUserEventId
= nullptr;
1190 mpGraphicFilter
.reset();
1192 if ( mbDeleteMatcher
)
1195 maPreviewIdle
.ClearInvokeHandler();
1197 ::comphelper::disposeComponent( mxFileDlg
);
1200 void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
1202 DBG_ASSERT( _pControlId
&& _pHelpId
, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" );
1203 if ( !_pControlId
|| !_pHelpId
)
1206 // forward these ids to the file picker
1209 const OUString
sHelpIdPrefix( INET_HID_SCHEME
);
1210 // the ids for the single controls
1211 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1212 if ( xControlAccess
.is() )
1214 while ( *_pControlId
)
1216 DBG_ASSERT( INetURLObject( OStringToOUString( *_pHelpId
, RTL_TEXTENCODING_UTF8
) ).GetProtocol() == INetProtocol::NotValid
, "Wrong HelpId!" );
1217 OUString sId
= sHelpIdPrefix
+
1218 OUString( *_pHelpId
, strlen( *_pHelpId
), RTL_TEXTENCODING_UTF8
);
1219 xControlAccess
->setValue( *_pControlId
, ControlActions::SET_HELP_URL
, makeAny( sId
) );
1221 ++_pControlId
; ++_pHelpId
;
1225 catch( const Exception
& )
1227 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" );
1231 IMPL_LINK_NOARG( FileDialogHelper_Impl
, InitControls
, void*, void )
1233 mnPostUserEventId
= nullptr;
1234 enablePasswordBox( true );
1235 updateFilterOptionsBox( );
1236 updateSelectionBox( );
1239 void FileDialogHelper_Impl::preExecute()
1242 setDefaultValues( );
1243 updatePreviewState( false );
1245 implInitializeFileName( );
1247 #if !(defined(MACOSX) && defined(MACOSX)) && !defined(_WIN32)
1248 // allow for dialog implementations which need to be executed before they return valid values for
1249 // current filter and such
1251 // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass
1252 // through before it returns from execution
1253 mnPostUserEventId
= Application::PostUserEvent( LINK( this, FileDialogHelper_Impl
, InitControls
) );
1255 // However, the macOS implementation's pickers run modally in execute and so the event doesn't
1256 // get through in time... so we call the methods directly
1257 enablePasswordBox( true );
1258 updateFilterOptionsBox( );
1259 updateSelectionBox( );
1263 void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult
)
1265 if ( ExecutableDialogResults::CANCEL
!= _nResult
)
1269 void FileDialogHelper_Impl::implInitializeFileName( )
1271 if ( maFileName
.isEmpty() )
1274 INetURLObject
aObj( maPath
);
1275 aObj
.Append( maFileName
);
1277 // in case we're operating as save dialog, and "auto extension" is checked,
1278 // cut the extension from the name
1279 if ( !(mbIsSaveDlg
&& mbHasAutoExt
) )
1284 bool bAutoExtChecked
= false;
1286 uno::Reference
< XFilePickerControlAccess
> xControlAccess( mxFileDlg
, UNO_QUERY
);
1287 if ( xControlAccess
.is()
1288 && ( xControlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 )
1293 if ( bAutoExtChecked
)
1294 { // cut the extension
1295 aObj
.removeExtension( );
1296 mxFileDlg
->setDefaultName(
1297 aObj
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
));
1301 catch( const Exception
& )
1303 OSL_FAIL( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" );
1307 sal_Int16
FileDialogHelper_Impl::implDoExecute()
1311 sal_Int16 nRet
= ExecutableDialogResults::CANCEL
;
1313 //On MacOSX the native file picker has to run in the primordial thread because of drawing issues
1314 //On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same
1315 //primordial thread as the ucb gnome-vfs2 provider was initialized in.
1321 if ( mbSystemPicker
)
1323 SolarMutexReleaser aSolarMutex
;
1324 nRet
= mxFileDlg
->execute();
1328 nRet
= mxFileDlg
->execute();
1330 catch( const Exception
& )
1332 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::implDoExecute" );
1336 postExecute( nRet
);
1341 void FileDialogHelper_Impl::implStartExecute()
1343 DBG_ASSERT( mxFileDlg
.is(), "invalid file dialog" );
1345 assert(mbAsyncPicker
);
1350 uno::Reference
< XAsynchronousExecutableDialog
> xAsyncDlg( mxFileDlg
, UNO_QUERY
);
1351 if ( xAsyncDlg
.is() )
1352 xAsyncDlg
->startExecuteModal( this );
1354 catch( const Exception
& )
1356 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::implDoExecute" );
1360 void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference
< XInterface
>& xPicker
, std::vector
<OUString
>& rpURLList
)
1364 // a) the new way (optional!)
1365 uno::Reference
< XFilePicker3
> xPickNew(xPicker
, UNO_QUERY
);
1368 Sequence
< OUString
> lFiles
= xPickNew
->getSelectedFiles();
1369 comphelper::sequenceToContainer(rpURLList
, lFiles
);
1372 // b) the olde way ... non optional.
1375 uno::Reference
< XFilePicker3
> xPickOld(xPicker
, UNO_QUERY_THROW
);
1376 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
1377 ::sal_Int32 nFiles
= lFiles
.getLength();
1380 rpURLList
.push_back(lFiles
[0]);
1382 else if ( nFiles
> 1 )
1384 INetURLObject
aPath( lFiles
[0] );
1385 aPath
.setFinalSlash();
1387 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
1390 aPath
.Append( lFiles
[i
] );
1392 aPath
.setName( lFiles
[i
] );
1394 rpURLList
.push_back(aPath
.GetMainURL(INetURLObject::DecodeMechanism::NONE
));
1399 mlLastURLs
= rpURLList
;
1402 ErrCode
FileDialogHelper_Impl::execute( std::vector
<OUString
>& rpURLList
,
1403 std::optional
<SfxAllItemSet
>& rpSet
,
1406 // rFilter is a pure output parameter, it shouldn't be used for anything else
1407 // changing this would surely break code
1408 // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog
1410 uno::Reference
< XFilePickerControlAccess
> xCtrlAccess( mxFileDlg
, UNO_QUERY
);
1412 // retrieves parameters from rpSet
1413 // for now only Password is used
1416 // check password checkbox if the document had password before
1419 const SfxBoolItem
* pPassItem
= SfxItemSet::GetItem
<SfxBoolItem
>(&*rpSet
, SID_PASSWORDINTERACTION
, false);
1420 mbPwdCheckBoxState
= ( pPassItem
!= nullptr && pPassItem
->GetValue() );
1422 // in case the document has password to modify, the dialog should be shown
1423 const SfxUnoAnyItem
* pPassToModifyItem
= SfxItemSet::GetItem
<SfxUnoAnyItem
>(&*rpSet
, SID_MODIFYPASSWORDINFO
, false);
1424 mbPwdCheckBoxState
|= ( pPassToModifyItem
&& pPassToModifyItem
->GetValue().hasValue() );
1427 const SfxBoolItem
* pSelectItem
= SfxItemSet::GetItem
<SfxBoolItem
>(&*rpSet
, SID_SELECTION
, false);
1429 mbSelection
= pSelectItem
->GetValue();
1431 mbSelectionEnabled
= false;
1433 // the password will be set in case user decide so
1434 rpSet
->ClearItem( SID_PASSWORDINTERACTION
);
1435 if (rpSet
->HasItem( SID_PASSWORD
))
1437 // As the SID_ENCRYPTIONDATA and SID_PASSWORD are using for setting password together, we need to clear them both.
1438 // Note: Do not remove SID_ENCRYPTIONDATA without SID_PASSWORD
1439 rpSet
->ClearItem( SID_PASSWORD
);
1440 rpSet
->ClearItem( SID_ENCRYPTIONDATA
);
1442 rpSet
->ClearItem( SID_RECOMMENDREADONLY
);
1443 rpSet
->ClearItem( SID_MODIFYPASSWORDINFO
);
1447 if ( mbHasPassword
&& !mbPwdCheckBoxState
)
1449 mbPwdCheckBoxState
= (
1450 SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::DocWarnRecommendPassword
) );
1455 if ( ! mxFileDlg
.is() )
1456 return ERRCODE_ABORT
;
1458 if ( ExecutableDialogResults::CANCEL
!= implDoExecute() )
1460 // create an itemset if there is no
1462 rpSet
.emplace( SfxGetpApp()->GetPool() );
1464 // the item should remain only if it was set by the dialog
1465 rpSet
->ClearItem( SID_SELECTION
);
1467 if( mbExport
&& mbHasSelectionBox
)
1471 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
1472 bool bSelection
= false;
1473 if ( aValue
>>= bSelection
)
1474 rpSet
->Put( SfxBoolItem( SID_SELECTION
, bSelection
) );
1476 catch( const IllegalArgumentException
& )
1478 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1483 // set the read-only flag. When inserting a file, this flag is always set
1485 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1488 if ( ( FILEOPEN_READONLY_VERSION
== m_nDialogType
) && xCtrlAccess
.is() )
1492 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY
, 0 );
1493 bool bReadOnly
= false;
1494 if ( ( aValue
>>= bReadOnly
) && bReadOnly
)
1495 rpSet
->Put( SfxBoolItem( SID_DOC_READONLY
, bReadOnly
) );
1497 catch( const IllegalArgumentException
& )
1499 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
1503 if ( mbHasVersions
&& xCtrlAccess
.is() )
1507 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION
,
1508 ControlActions::GET_SELECTED_ITEM_INDEX
);
1509 sal_Int32 nVersion
= 0;
1510 if ( ( aValue
>>= nVersion
) && nVersion
> 0 )
1511 // open a special version; 0 == current version
1512 rpSet
->Put( SfxInt16Item( SID_VERSION
, static_cast<short>(nVersion
) ) );
1514 catch( const IllegalArgumentException
& ){}
1518 getRealFilter( rFilter
);
1520 std::shared_ptr
<const SfxFilter
> pCurrentFilter
= getCurentSfxFilter();
1522 // fill the rpURLList
1523 implGetAndCacheFiles( mxFileDlg
, rpURLList
);
1524 if ( rpURLList
.empty() )
1525 return ERRCODE_ABORT
;
1527 // check, whether or not we have to display a password box
1528 if ( pCurrentFilter
&& mbHasPassword
&& mbIsPwdEnabled
&& xCtrlAccess
.is() )
1532 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, 0 );
1533 bool bPassWord
= false;
1534 if ( ( aValue
>>= bPassWord
) && bPassWord
)
1536 // ask for a password
1537 OUString
aDocName(rpURLList
[0]);
1538 ErrCode errCode
= RequestPassword(pCurrentFilter
, aDocName
, &*rpSet
, GetFrameInterface());
1539 if (errCode
!= ERRCODE_NONE
)
1543 catch( const IllegalArgumentException
& ){}
1545 // check, whether or not we have to display a key selection box
1546 if ( pCurrentFilter
&& mbHasPassword
&& xCtrlAccess
.is() )
1550 Any aValue
= xCtrlAccess
->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION
, 0 );
1552 if ( ( aValue
>>= bGpg
) && bGpg
)
1554 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
1560 aEncryptionData
= ::comphelper::OStorageHelper::CreateGpgPackageEncryptionData();
1561 break; // user cancelled or we've some keys now
1563 catch( const IllegalArgumentException
& )
1565 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(mpFrameWeld
,
1566 VclMessageType::Warning
, VclButtonsType::Ok
,
1567 SfxResId(RID_SVXSTR_GPG_ENCRYPT_FAILURE
)));
1572 if ( aEncryptionData
.hasElements() )
1573 rpSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
1576 catch( const IllegalArgumentException
& ){}
1579 SaveLastUsedFilter();
1580 return ERRCODE_NONE
;
1583 return ERRCODE_ABORT
;
1586 ErrCode
FileDialogHelper_Impl::execute()
1588 if ( ! mxFileDlg
.is() )
1589 return ERRCODE_ABORT
;
1591 sal_Int16 nRet
= implDoExecute();
1593 maPath
= mxFileDlg
->getDisplayDirectory();
1595 if ( ExecutableDialogResults::CANCEL
== nRet
)
1596 return ERRCODE_ABORT
;
1599 return ERRCODE_NONE
;
1603 OUString
FileDialogHelper_Impl::getPath() const
1607 if ( mxFileDlg
.is() )
1608 aPath
= mxFileDlg
->getDisplayDirectory();
1610 if ( aPath
.isEmpty() )
1616 OUString
FileDialogHelper_Impl::getFilter() const
1618 OUString aFilter
= getCurrentFilterUIName();
1620 if( aFilter
.isEmpty() )
1621 aFilter
= maCurFilter
;
1626 void FileDialogHelper_Impl::getRealFilter( OUString
& _rFilter
) const
1628 _rFilter
= getCurrentFilterUIName();
1630 if ( _rFilter
.isEmpty() )
1631 _rFilter
= maCurFilter
;
1633 if ( !_rFilter
.isEmpty() && mpMatcher
)
1635 std::shared_ptr
<const SfxFilter
> pFilter
=
1636 mpMatcher
->GetFilter4UIName( _rFilter
, m_nMustFlags
, m_nDontFlags
);
1637 _rFilter
= pFilter
? pFilter
->GetFilterName() : OUString();
1641 void FileDialogHelper_Impl::verifyPath()
1644 // lp#905355, fdo#43895
1645 // Check that the file has read only permission and is in /tmp -- this is
1646 // the case if we have opened the file from the web with firefox only.
1647 if (maFileName
.isEmpty()) {
1650 INetURLObject
url(maPath
);
1651 if (url
.GetProtocol() != INetProtocol::File
1652 || url
.getName(0, true, INetURLObject::DecodeMechanism::WithCharset
) != "tmp")
1656 if (maFileName
.indexOf('/') != -1) {
1657 SAL_WARN("sfx.dialog", maFileName
<< " contains /");
1661 maFileName
, false, INetURLObject::LAST_SEGMENT
,
1662 INetURLObject::EncodeMechanism::All
);
1664 osl::FileBase::RC e
= osl::FileBase::getSystemPathFromFileURL(
1665 url
.GetMainURL(INetURLObject::DecodeMechanism::NONE
), sysPathU
);
1666 if (e
!= osl::FileBase::E_None
) {
1669 "getSystemPathFromFileURL("
1670 << url
.GetMainURL(INetURLObject::DecodeMechanism::NONE
) << ") failed with "
1675 if (!sysPathU
.convertToString(
1676 &sysPathC
, osl_getThreadTextEncoding(),
1677 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1678 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1682 "convertToString(" << sysPathU
<< ") failed for encoding "
1683 << +osl_getThreadTextEncoding());
1686 struct stat aFileStat
;
1687 if (stat(sysPathC
.getStr(), &aFileStat
) == -1) {
1688 SAL_WARN( "sfx.dialog", "stat(" << sysPathC
<< ") failed with errno " << errno
);
1691 if ((aFileStat
.st_mode
& (S_IRWXO
| S_IRWXG
| S_IRWXU
)) == S_IRUSR
) {
1692 maPath
= SvtPathOptions().GetWorkPath();
1693 mxFileDlg
->setDisplayDirectory( maPath
);
1700 void FileDialogHelper_Impl::displayFolder( const OUString
& _rPath
)
1702 if ( _rPath
.isEmpty() )
1707 if ( mxFileDlg
.is() )
1711 mxFileDlg
->setDisplayDirectory( maPath
);
1714 catch( const IllegalArgumentException
& )
1716 TOOLS_WARN_EXCEPTION( "sfx", "FileDialogHelper_Impl::displayFolder" );
1721 void FileDialogHelper_Impl::setFileName( const OUString
& _rFile
)
1723 maFileName
= _rFile
;
1724 if ( mxFileDlg
.is() )
1728 mxFileDlg
->setDefaultName( maFileName
);
1731 catch( const IllegalArgumentException
& )
1733 TOOLS_WARN_EXCEPTION( "sfx", "FileDialogHelper_Impl::setFileName" );
1738 void FileDialogHelper_Impl::setFilter( const OUString
& rFilter
)
1740 DBG_ASSERT( rFilter
.indexOf(':') == -1, "Old filter name used!");
1742 maCurFilter
= rFilter
;
1744 if ( !rFilter
.isEmpty() && mpMatcher
)
1746 std::shared_ptr
<const SfxFilter
> pFilter
= mpMatcher
->GetFilter4FilterName(
1747 rFilter
, m_nMustFlags
, m_nDontFlags
);
1749 maCurFilter
= pFilter
->GetUIName();
1752 if ( !maCurFilter
.isEmpty() && mxFileDlg
.is() )
1756 mxFileDlg
->setCurrentFilter( maCurFilter
);
1758 catch( const IllegalArgumentException
& ){}
1762 void FileDialogHelper_Impl::createMatcher( const OUString
& rFactory
)
1764 if (mbDeleteMatcher
)
1767 mpMatcher
= new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
1768 mbDeleteMatcher
= true;
1771 void FileDialogHelper_Impl::addFilters( const OUString
& rFactory
,
1772 SfxFilterFlags nMust
,
1773 SfxFilterFlags nDont
)
1775 if ( ! mxFileDlg
.is() )
1778 if (mbDeleteMatcher
)
1781 // we still need a matcher to convert UI names to filter names
1782 if ( rFactory
.isEmpty() )
1784 SfxApplication
*pSfxApp
= SfxGetpApp();
1785 mpMatcher
= &pSfxApp
->GetFilterMatcher();
1786 mbDeleteMatcher
= false;
1790 mpMatcher
= new SfxFilterMatcher( rFactory
);
1791 mbDeleteMatcher
= true;
1794 uno::Reference
< XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
1795 uno::Reference
< XContainerQuery
> xFilterCont(
1796 xSMGR
->createInstance("com.sun.star.document.FilterFactory"),
1798 if ( ! xFilterCont
.is() )
1801 m_nMustFlags
|= nMust
;
1802 m_nDontFlags
|= nDont
;
1804 // create the list of filters
1806 "getSortedFilterList()"
1808 rFactory
+ // use long name here !
1810 OUString::number(static_cast<sal_Int32
>(m_nMustFlags
)) +
1812 OUString::number(static_cast<sal_Int32
>(m_nDontFlags
));
1814 uno::Reference
< XEnumeration
> xResult
;
1817 xResult
= xFilterCont
->createSubSetEnumerationByQuery(sQuery
);
1819 catch( const uno::Exception
& )
1821 SAL_WARN( "sfx.dialog", "Could not get filters from the configuration!" );
1824 TSortedFilterList
aIter (xResult
);
1826 // append the filters
1827 OUString sFirstFilter
;
1828 if (OPEN
== lcl_OpenOrSave(m_nDialogType
))
1829 ::sfx2::appendFiltersForOpen( aIter
, mxFileDlg
, sFirstFilter
, *this );
1830 else if ( mbExport
)
1831 ::sfx2::appendExportFilters( aIter
, mxFileDlg
, sFirstFilter
, *this );
1833 ::sfx2::appendFiltersForSave( aIter
, mxFileDlg
, sFirstFilter
, *this, rFactory
);
1835 // set our initial selected filter (if we do not already have one)
1836 if ( maSelectFilter
.isEmpty() )
1837 maSelectFilter
= sFirstFilter
;
1840 void FileDialogHelper_Impl::addFilter( const OUString
& rFilterName
,
1841 const OUString
& rExtension
)
1843 if ( ! mxFileDlg
.is() )
1848 mxFileDlg
->appendFilter( rFilterName
, rExtension
);
1850 if ( maSelectFilter
.isEmpty() )
1851 maSelectFilter
= rFilterName
;
1853 catch( const IllegalArgumentException
& )
1855 SAL_WARN( "sfx.dialog", "Could not append Filter" << rFilterName
);
1859 void FileDialogHelper_Impl::addGraphicFilter()
1861 if ( ! mxFileDlg
.is() )
1864 // create the list of filters
1865 mpGraphicFilter
.reset( new GraphicFilter
);
1866 sal_uInt16 i
, j
, nCount
= mpGraphicFilter
->GetImportFormatCount();
1868 // compute the extension string for all known import filters
1869 OUString aExtensions
;
1871 for ( i
= 0; i
< nCount
; i
++ )
1876 OUString sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1877 if ( sWildcard
.isEmpty() )
1879 if ( aExtensions
.indexOf( sWildcard
) == -1 )
1881 if ( !aExtensions
.isEmpty() )
1883 aExtensions
+= sWildcard
;
1889 if ( aExtensions
.getLength() > 240 )
1890 aExtensions
= FILEDIALOG_FILTER_ALL
;
1892 bool bIsInOpenMode
= isInOpenMode();
1896 // if the extension is not "All files", insert "All images"
1897 if (aExtensions
!= FILEDIALOG_FILTER_ALL
)
1899 OUString aAllFilterName
= SfxResId(STR_SFX_IMPORT_ALL_IMAGES
);
1900 aAllFilterName
= ::sfx2::addExtension( aAllFilterName
, aExtensions
, bIsInOpenMode
, *this );
1901 mxFileDlg
->appendFilter( aAllFilterName
, aExtensions
);
1902 maSelectFilter
= aAllFilterName
; // and make it the default
1905 // rhbz#1715109 always include All files *.* or *
1906 OUString aAllFilesName
= SfxResId( STR_SFX_FILTERNAME_ALL
);
1907 aAllFilesName
= ::sfx2::addExtension( aAllFilesName
, FILEDIALOG_FILTER_ALL
, bIsInOpenMode
, *this );
1908 mxFileDlg
->appendFilter( aAllFilesName
, FILEDIALOG_FILTER_ALL
);
1910 // if the extension is "All files", make that the default
1911 if (aExtensions
== FILEDIALOG_FILTER_ALL
)
1912 maSelectFilter
= aAllFilesName
;
1914 catch( const IllegalArgumentException
& )
1916 SAL_WARN( "sfx.dialog", "Could not append Filter" );
1919 // Now add the filter
1920 for ( i
= 0; i
< nCount
; i
++ )
1922 OUString aName
= mpGraphicFilter
->GetImportFormatName( i
);
1927 OUString sWildcard
= mpGraphicFilter
->GetImportWildcard( i
, j
++ );
1928 if ( sWildcard
.isEmpty() )
1930 if ( aExt
.indexOf( sWildcard
) == -1 )
1932 if ( !aExt
.isEmpty() )
1937 aName
= ::sfx2::addExtension( aName
, aExt
, bIsInOpenMode
, *this );
1940 mxFileDlg
->appendFilter( aName
, aExt
);
1942 catch( const IllegalArgumentException
& )
1944 SAL_WARN( "sfx.dialog", "Could not append Filter" );
1949 constexpr OUStringLiteral GRF_CONFIG_STR
= u
" ";
1950 constexpr OUStringLiteral STD_CONFIG_STR
= u
"1 ";
1952 static void SetToken( OUString
& rOrigStr
, sal_Int32 nToken
, sal_Unicode cTok
, std::u16string_view rStr
)
1954 const sal_Unicode
* pStr
= rOrigStr
.getStr();
1955 sal_Int32 nLen
= rOrigStr
.getLength();
1957 sal_Int32 nFirstChar
= 0;
1958 sal_Int32 i
= nFirstChar
;
1960 // Determine token position and length
1964 // Increase token count if match
1965 if ( *pStr
== cTok
)
1969 if ( nTok
== nToken
)
1973 if ( nTok
> nToken
)
1982 if ( nTok
>= nToken
)
1983 rOrigStr
= rOrigStr
.replaceAt( nFirstChar
, i
-nFirstChar
, rStr
);
1988 void SaveLastDirectory(OUString
const& sContext
, OUString
const& sDirectory
)
1990 if (sContext
.isEmpty())
1993 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(
1994 comphelper::ConfigurationChanges::create());
1995 Reference
<container::XNameContainer
> set(
1996 officecfg::Office::Common::Misc::FilePickerLastDirectory::get(batch
));
2002 v
= set
->getByName(sContext
);
2005 catch (container::NoSuchElementException
&)
2011 Reference
<XPropertySet
> el(v
.get
<Reference
<XPropertySet
>>(), UNO_SET_THROW
);
2012 el
->setPropertyValue("LastPath", makeAny(sDirectory
));
2016 Reference
<XPropertySet
> el(
2017 (Reference
<lang::XSingleServiceFactory
>(set
, UNO_QUERY_THROW
)->createInstance()),
2019 el
->setPropertyValue("LastPath", makeAny(sDirectory
));
2020 Any
v2(makeAny(el
));
2021 set
->insertByName(sContext
, v2
);
2027 void FileDialogHelper_Impl::saveConfig()
2029 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
2037 SvtViewOptions
aDlgOpt( EViewType::Dialog
, IMPGRF_CONFIGNAME
);
2041 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0 );
2042 bool bValue
= false;
2044 OUString
aUserData(GRF_CONFIG_STR
);
2045 SetToken( aUserData
, 1, ' ', OUString::number( static_cast<sal_Int32
>(bValue
) ) );
2047 INetURLObject
aObj( getPath() );
2049 if ( aObj
.GetProtocol() == INetProtocol::File
)
2050 SetToken( aUserData
, 2, ' ', aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
2052 OUString aFilter
= getFilter();
2053 aFilter
= EncodeSpaces_Impl( aFilter
);
2054 SetToken( aUserData
, 3, ' ', aFilter
);
2056 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( aUserData
) );
2058 catch( const IllegalArgumentException
& ){}
2062 bool bWriteConfig
= false;
2063 SvtViewOptions
aDlgOpt( EViewType::Dialog
, IODLG_CONFIGNAME
);
2064 OUString
aUserData(STD_CONFIG_STR
);
2066 if ( aDlgOpt
.Exists() )
2068 Any aUserItem
= aDlgOpt
.GetUserItem( USERITEM_NAME
);
2070 if ( aUserItem
>>= aTemp
)
2078 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0 );
2079 bool bAutoExt
= true;
2080 aValue
>>= bAutoExt
;
2081 SetToken( aUserData
, 0, ' ', OUString::number( static_cast<sal_Int32
>(bAutoExt
) ) );
2082 bWriteConfig
= true;
2084 catch( const IllegalArgumentException
& ){}
2087 if ( ! mbIsSaveDlg
)
2089 OUString aPath
= getPath();
2090 if ( comphelper::isFileUrl( aPath
) )
2092 SetToken( aUserData
, 1, ' ', aPath
);
2093 bWriteConfig
= true;
2097 if( mbHasSelectionBox
&& mbSelectionFltrEnabled
)
2101 aValue
= xDlg
->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0 );
2102 bool bSelection
= true;
2103 aValue
>>= bSelection
;
2104 if ( comphelper::string::getTokenCount(aUserData
, ' ') < 3 )
2106 SetToken( aUserData
, 2, ' ', OUString::number( static_cast<sal_Int32
>(bSelection
) ) );
2107 bWriteConfig
= true;
2109 catch( const IllegalArgumentException
& ){}
2113 aDlgOpt
.SetUserItem( USERITEM_NAME
, makeAny( aUserData
) );
2116 // Store to config, if explicit context is set. Otherwise store in (global) runtime var.
2117 if (meContext
!= FileDialogHelper::UnknownContext
)
2119 SaveLastDirectory(FileDialogHelper::contextToString(meContext
), getPath());
2123 SfxApplication
*pSfxApp
= SfxGetpApp();
2124 pSfxApp
->SetLastDir_Impl( getPath() );
2128 OUString
FileDialogHelper_Impl::getInitPath(const OUString
& _rFallback
,
2129 const sal_Int32 _nFallbackToken
)
2132 // Load from config, if explicit context is set. Otherwise load from (global) runtime var.
2133 if (meContext
!= FileDialogHelper::UnknownContext
)
2135 OUString sContext
= FileDialogHelper::contextToString(meContext
);
2136 Reference
<XNameAccess
> set(officecfg::Office::Common::Misc::FilePickerLastDirectory::get());
2140 v
= set
->getByName(sContext
);
2141 Reference
<XPropertySet
> el(v
.get
<Reference
<XPropertySet
>>(), UNO_SET_THROW
);
2142 sPath
= el
->getPropertyValue("LastPath").get
<OUString
>();
2144 catch (NoSuchElementException
&)
2150 SfxApplication
*pSfxApp
= SfxGetpApp();
2151 sPath
= pSfxApp
->GetLastDir_Impl();
2154 if ( sPath
.isEmpty() )
2155 sPath
= _rFallback
.getToken( _nFallbackToken
, ' ' );
2157 // check if the path points to a valid (accessible) directory
2158 bool bValid
= false;
2159 if ( !sPath
.isEmpty() )
2161 OUString
sPathCheck( sPath
);
2162 if ( sPathCheck
[ sPathCheck
.getLength() - 1 ] != '/' )
2167 ::ucbhelper::Content
aContent( sPathCheck
,
2168 utl::UCBContentHelper::getDefaultCommandEnvironment(),
2169 comphelper::getProcessComponentContext() );
2170 bValid
= aContent
.isFolder();
2172 catch( const Exception
& ) {}
2179 void FileDialogHelper_Impl::loadConfig()
2181 uno::Reference
< XFilePickerControlAccess
> xDlg( mxFileDlg
, UNO_QUERY
);
2189 SvtViewOptions
aViewOpt( EViewType::Dialog
, IMPGRF_CONFIGNAME
);
2192 if ( aViewOpt
.Exists() )
2194 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2196 if ( aUserItem
>>= aTemp
)
2200 if ( !aUserData
.isEmpty() )
2204 // respect the last "insert as link" state
2205 bool bLink
= aUserData
.getToken( 0, ' ' ).toInt32();
2207 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK
, 0, aValue
);
2209 // respect the last "show preview" state
2210 bool bShowPreview
= aUserData
.getToken( 1, ' ' ).toInt32();
2211 aValue
<<= bShowPreview
;
2212 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW
, 0, aValue
);
2214 if ( maPath
.isEmpty() )
2215 displayFolder( getInitPath( aUserData
, 2 ) );
2217 if ( maCurFilter
.isEmpty() )
2219 OUString aFilter
= aUserData
.getToken( 3, ' ' );
2220 aFilter
= DecodeSpaces_Impl( aFilter
);
2221 setFilter( aFilter
);
2224 // set the member so we know that we have to show the preview
2225 mbShowPreview
= bShowPreview
;
2227 catch( const IllegalArgumentException
& ){}
2230 if ( maPath
.isEmpty() )
2231 displayFolder( SvtPathOptions().GetWorkPath() );
2235 SvtViewOptions
aViewOpt( EViewType::Dialog
, IODLG_CONFIGNAME
);
2238 if ( aViewOpt
.Exists() )
2240 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2242 if ( aUserItem
>>= aTemp
)
2246 if ( aUserData
.isEmpty() )
2247 aUserData
= STD_CONFIG_STR
;
2249 if ( maPath
.isEmpty() )
2250 displayFolder( getInitPath( aUserData
, 1 ) );
2254 sal_Int32 nFlag
= aUserData
.getToken( 0, ' ' ).toInt32();
2255 aValue
<<= static_cast<bool>(nFlag
);
2258 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0, aValue
);
2260 catch( const IllegalArgumentException
& ){}
2263 if( mbHasSelectionBox
)
2265 sal_Int32 nFlag
= aUserData
.getToken( 2, ' ' ).toInt32();
2266 aValue
<<= static_cast<bool>(nFlag
);
2269 xDlg
->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION
, 0, aValue
);
2271 catch( const IllegalArgumentException
& ){}
2274 if ( maPath
.isEmpty() )
2275 displayFolder( SvtPathOptions().GetWorkPath() );
2279 void FileDialogHelper_Impl::setDefaultValues()
2281 // when no filter is set, we set the currentFilter to <all>
2282 if ( maCurFilter
.isEmpty() && !maSelectFilter
.isEmpty() )
2286 mxFileDlg
->setCurrentFilter( maSelectFilter
);
2288 catch( const IllegalArgumentException
& )
2292 // when no path is set, we use the standard 'work' folder
2293 if ( maPath
.isEmpty() )
2295 OUString aWorkFolder
= SvtPathOptions().GetWorkPath();
2298 mxFileDlg
->setDisplayDirectory( aWorkFolder
);
2300 catch( const Exception
& )
2302 TOOLS_WARN_EXCEPTION( "sfx.dialog", "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" );
2307 bool FileDialogHelper_Impl::isShowFilterExtensionEnabled() const
2309 return !maFilters
.empty();
2312 void FileDialogHelper_Impl::addFilterPair( const OUString
& rFilter
,
2313 const OUString
& rFilterWithExtension
)
2315 maFilters
.emplace_back( rFilter
, rFilterWithExtension
);
2319 OUString
FileDialogHelper_Impl::getFilterName( std::u16string_view rFilterWithExtension
) const
2322 for (auto const& filter
: maFilters
)
2324 if (filter
.Second
== rFilterWithExtension
)
2326 sRet
= filter
.First
;
2333 OUString
FileDialogHelper_Impl::getFilterWithExtension( std::u16string_view rFilter
) const
2336 for (auto const& filter
: maFilters
)
2338 if ( filter
.First
== rFilter
)
2340 sRet
= filter
.Second
;
2347 void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext
)
2349 meContext
= _eNewContext
;
2351 std::optional
<OUString
> pConfigId
= GetLastFilterConfigId( _eNewContext
);
2353 LoadLastUsedFilter( *pConfigId
);
2358 FileDialogHelper::FileDialogHelper(
2359 sal_Int16 nDialogType
,
2360 FileDialogFlags nFlags
,
2361 const OUString
& rFact
,
2362 SfxFilterFlags nMust
,
2363 SfxFilterFlags nDont
,
2364 weld::Window
* pPreferredParent
)
2366 mpImpl(new FileDialogHelper_Impl(this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, pPreferredParent
))
2369 // create the list of filters
2371 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2374 FileDialogHelper::FileDialogHelper(
2375 sal_Int16 nDialogType
,
2376 FileDialogFlags nFlags
,
2377 const OUString
& rFact
,
2379 SfxFilterFlags nMust
,
2380 SfxFilterFlags nDont
,
2381 const OUString
& rStandardDir
,
2382 const css::uno::Sequence
< OUString
>& rDenyList
,
2383 weld::Window
* pPreferredParent
)
2385 mpImpl( new FileDialogHelper_Impl( this, nDialogType
, nFlags
, nDialog
, pPreferredParent
, rStandardDir
, rDenyList
) )
2387 // create the list of filters
2389 SfxObjectShell::GetServiceNameFromFactory(rFact
), nMust
, nDont
);
2392 FileDialogHelper::FileDialogHelper(sal_Int16 nDialogType
, FileDialogFlags nFlags
, weld::Window
* pPreferredParent
)
2394 mpImpl( new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, pPreferredParent
) )
2398 FileDialogHelper::FileDialogHelper(
2399 sal_Int16 nDialogType
,
2400 FileDialogFlags nFlags
,
2401 const OUString
& aFilterUIName
,
2402 const OUString
& aExtName
,
2403 const OUString
& rStandardDir
,
2404 const css::uno::Sequence
< OUString
>& rDenyList
,
2405 weld::Window
* pPreferredParent
)
2407 mpImpl( new FileDialogHelper_Impl( this, nDialogType
, nFlags
, SFX2_IMPL_DIALOG_CONFIG
, pPreferredParent
, rStandardDir
, rDenyList
) )
2409 // the wildcard here is expected in form "*.extension"
2411 if ( aExtName
.indexOf( '*' ) != 0 )
2413 if ( !aExtName
.isEmpty() && aExtName
.indexOf( '.' ) != 0 )
2419 aWildcard
+= aExtName
;
2421 OUString
const aUIString
= ::sfx2::addExtension(
2422 aFilterUIName
, aWildcard
, (OPEN
== lcl_OpenOrSave(mpImpl
->m_nDialogType
)), *mpImpl
);
2423 AddFilter( aUIString
, aWildcard
);
2426 FileDialogHelper::~FileDialogHelper()
2431 void FileDialogHelper::CreateMatcher( const OUString
& rFactory
)
2433 mpImpl
->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory
) );
2436 void FileDialogHelper::SetControlHelpIds( const sal_Int16
* _pControlId
, const char** _pHelpId
)
2438 mpImpl
->setControlHelpIds( _pControlId
, _pHelpId
);
2441 void FileDialogHelper::SetContext( Context _eNewContext
)
2443 mpImpl
->SetContext( _eNewContext
);
2446 OUString
FileDialogHelper::contextToString(Context context
)
2448 // These strings are used in the configuration, to store the last used directory for each context.
2449 // Please don't change them.
2451 case AcceleratorConfig
:
2452 return "AcceleratorConfig";
2454 return "AutoRedact";
2455 case BaseDataSource
:
2456 return "BaseDataSource";
2458 return "BaseSaveAs";
2459 case BasicExportDialog
:
2460 return "BasicExportDialog";
2461 case BasicExportPackage
:
2462 return "BasicExportPackage";
2463 case BasicExportSource
:
2464 return "BasicExportSource";
2465 case BasicImportDialog
:
2466 return "BasicImportDialog";
2467 case BasicImportSource
:
2468 return "BasicImportSource";
2469 case BasicInsertLib
:
2470 return "BasicInsertLib";
2471 case BulletsAddImage
:
2472 return "BulletsAddImage";
2473 case CalcDataProvider
:
2474 return "CalcDataProvider";
2475 case CalcDataStream
:
2476 return "CalcDataStream";
2478 return "CalcExport";
2480 return "CalcSaveAs";
2482 return "CalcXMLSource";
2484 return "ExportImage";
2485 case ExtensionManager
:
2486 return "ExtensionManager";
2487 case FormsAddInstance
:
2488 return "FormsAddInstance";
2489 case FormsInsertImage
:
2490 return "FormsInsertImage";
2492 return "LinkClientOLE";
2493 case LinkClientFile
:
2494 return "LinkClientFile";
2495 case DrawImpressInsertFile
:
2496 return "DrawImpressInsertFile";
2497 case DrawImpressOpenSound
:
2498 return "DrawImpressOpenSound";
2500 return "DrawExport";
2502 return "DrawSaveAs";
2504 return "IconImport";
2505 case ImpressClickAction
:
2506 return "ImpressClickAction";
2508 return "ImpressExport";
2509 case ImpressPhotoDialog
:
2510 return "ImpressPhotoDialog";
2512 return "ImpressSaveAs";
2518 return "InsertImage";
2522 return "InsertMedia";
2524 return "JavaClassPath";
2525 case ReportInsertImage
:
2526 return "ReportInsertImage";
2527 case ScreenshotAnnotation
:
2528 return "ScreenshotAnnotation";
2530 return "SignatureLine";
2531 case TemplateImport
:
2532 return "TemplateImport";
2533 case WriterCreateAddressList
:
2534 return "WriterCreateAddressList";
2536 return "WriterExport";
2537 case WriterImportAutotext
:
2538 return "WriterImportAutotext";
2539 case WriterInsertDoc
:
2540 return "WriterInsertDoc";
2541 case WriterInsertHyperlink
:
2542 return "WriterInsertHyperlink";
2543 case WriterInsertImage
:
2544 return "WriterInsertImage";
2545 case WriterInsertScript
:
2546 return "WriterInsertScript";
2547 case WriterLoadTemplate
:
2548 return "WriterLoadTemplate";
2549 case WriterMailMerge
:
2550 return "WriterMailMerge";
2551 case WriterMailMergeSaveAs
:
2552 return "WriterMailMergeSaveAs";
2553 case WriterNewHTMLGlobalDoc
:
2554 return "WriterNewHTMLGlobalDoc";
2555 case WriterRegisterDataSource
:
2556 return "WriterRegisterDataSource";
2558 return "WriterSaveAs";
2559 case WriterSaveHTML
:
2560 return "WriterSaveHTML";
2561 case XMLFilterSettings
:
2562 return "XMLFilterSettings";
2563 case UnknownContext
:
2569 IMPL_LINK_NOARG(FileDialogHelper
, ExecuteSystemFilePicker
, void*, void)
2571 m_nError
= mpImpl
->execute();
2572 m_aDialogClosedLink
.Call( this );
2575 // rDirPath has to be a directory
2576 ErrCode
FileDialogHelper::Execute( std::vector
<OUString
>& rpURLList
,
2577 std::optional
<SfxAllItemSet
>& rpSet
,
2579 const OUString
& rDirPath
)
2581 SetDisplayFolder( rDirPath
);
2582 return mpImpl
->execute( rpURLList
, rpSet
, rFilter
);
2586 ErrCode
FileDialogHelper::Execute()
2588 return mpImpl
->execute();
2591 ErrCode
FileDialogHelper::Execute( std::optional
<SfxAllItemSet
>& rpSet
,
2595 std::vector
<OUString
> rURLList
;
2596 nRet
= mpImpl
->execute(rURLList
, rpSet
, rFilter
);
2600 void FileDialogHelper::StartExecuteModal( const Link
<FileDialogHelper
*,void>& rEndDialogHdl
)
2602 m_aDialogClosedLink
= rEndDialogHdl
;
2603 m_nError
= ERRCODE_NONE
;
2604 if (!mpImpl
->isAsyncFilePicker())
2605 Application::PostUserEvent( LINK( this, FileDialogHelper
, ExecuteSystemFilePicker
) );
2607 mpImpl
->implStartExecute();
2610 sal_Int16
FileDialogHelper::GetDialogType() const { return mpImpl
? mpImpl
->m_nDialogType
: 0; }
2612 bool FileDialogHelper::IsPasswordEnabled() const
2614 return mpImpl
&& mpImpl
->isPasswordEnabled();
2617 OUString
FileDialogHelper::GetRealFilter() const
2621 mpImpl
->getRealFilter( sFilter
);
2625 void FileDialogHelper::SetTitle( const OUString
& rNewTitle
)
2627 if ( mpImpl
->mxFileDlg
.is() )
2628 mpImpl
->mxFileDlg
->setTitle( rNewTitle
);
2631 OUString
FileDialogHelper::GetPath() const
2635 if ( !mpImpl
->mlLastURLs
.empty())
2636 return mpImpl
->mlLastURLs
[0];
2638 if ( mpImpl
->mxFileDlg
.is() )
2640 Sequence
< OUString
> aPathSeq
= mpImpl
->mxFileDlg
->getFiles();
2642 if ( aPathSeq
.getLength() == 1 )
2644 aPath
= aPathSeq
[0];
2651 Sequence
< OUString
> FileDialogHelper::GetMPath() const
2653 if ( !mpImpl
->mlLastURLs
.empty())
2654 return comphelper::containerToSequence(mpImpl
->mlLastURLs
);
2656 if ( mpImpl
->mxFileDlg
.is() )
2657 return mpImpl
->mxFileDlg
->getFiles();
2660 Sequence
< OUString
> aEmpty
;
2665 Sequence
< OUString
> FileDialogHelper::GetSelectedFiles() const
2667 // a) the new way (optional!)
2668 uno::Sequence
< OUString
> aResultSeq
;
2669 if (mpImpl
->mxFileDlg
.is())
2671 aResultSeq
= mpImpl
->mxFileDlg
->getSelectedFiles();
2673 // b) the olde way ... non optional.
2676 uno::Reference
< XFilePicker
> xPickOld(mpImpl
->mxFileDlg
, UNO_QUERY_THROW
);
2677 Sequence
< OUString
> lFiles
= xPickOld
->getFiles();
2678 ::sal_Int32 nFiles
= lFiles
.getLength();
2681 aResultSeq
= Sequence
< OUString
>( nFiles
-1 );
2682 auto pResultSeq
= aResultSeq
.getArray();
2684 INetURLObject
aPath( lFiles
[0] );
2685 aPath
.setFinalSlash();
2687 for (::sal_Int32 i
= 1; i
< nFiles
; i
++)
2690 aPath
.Append( lFiles
[i
] );
2692 aPath
.setName( lFiles
[i
] );
2694 pResultSeq
[i
-1] = aPath
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
2698 aResultSeq
= lFiles
;
2704 OUString
FileDialogHelper::GetDisplayDirectory() const
2706 return mpImpl
->getPath();
2709 OUString
FileDialogHelper::GetCurrentFilter() const
2711 return mpImpl
->getFilter();
2714 ErrCode
FileDialogHelper::GetGraphic( Graphic
& rGraphic
) const
2716 return mpImpl
->getGraphic( rGraphic
);
2719 static int impl_isFolder( const OUString
& rPath
)
2723 ::ucbhelper::Content
aContent(
2724 rPath
, uno::Reference
< ucb::XCommandEnvironment
> (),
2725 comphelper::getProcessComponentContext() );
2726 if ( aContent
.isFolder() )
2731 catch ( const Exception
& )
2738 void FileDialogHelper::SetDisplayDirectory( const OUString
& _rPath
)
2740 if ( _rPath
.isEmpty() )
2743 // if the given path isn't a folder, we cut off the last part
2744 // and take it as filename and the rest of the path should be
2747 INetURLObject
aObj( _rPath
);
2749 OUString sFileName
= aObj
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
2750 aObj
.removeSegment();
2751 OUString sPath
= aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
2753 int nIsFolder
= impl_isFolder( _rPath
);
2754 if ( nIsFolder
== 0 ||
2755 ( nIsFolder
== -1 && impl_isFolder( sPath
) == 1 ) )
2757 mpImpl
->setFileName( sFileName
);
2758 mpImpl
->displayFolder( sPath
);
2762 INetURLObject
aObjPathName( _rPath
);
2763 OUString
sFolder( aObjPathName
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
2764 if ( sFolder
.isEmpty() )
2766 // _rPath is not a valid path -> fallback to home directory
2767 osl::Security aSecurity
;
2768 aSecurity
.getHomeDir( sFolder
);
2770 mpImpl
->displayFolder( sFolder
);
2774 void FileDialogHelper::SetDisplayFolder( const OUString
& _rURL
)
2776 mpImpl
->displayFolder( _rURL
);
2779 void FileDialogHelper::SetFileName( const OUString
& _rFileName
)
2781 mpImpl
->setFileName( _rFileName
);
2784 void FileDialogHelper::AddFilter( const OUString
& rFilterName
,
2785 const OUString
& rExtension
)
2787 mpImpl
->addFilter( rFilterName
, rExtension
);
2790 void FileDialogHelper::SetCurrentFilter( const OUString
& rFilter
)
2792 OUString
sFilter( rFilter
);
2793 if ( mpImpl
->isShowFilterExtensionEnabled() )
2794 sFilter
= mpImpl
->getFilterWithExtension( rFilter
);
2795 mpImpl
->setFilter( sFilter
);
2798 const uno::Reference
< XFilePicker3
>& FileDialogHelper::GetFilePicker() const
2800 return mpImpl
->mxFileDlg
;
2803 // XFilePickerListener Methods
2804 void FileDialogHelper::FileSelectionChanged()
2806 mpImpl
->handleFileSelectionChanged();
2809 void FileDialogHelper::DirectoryChanged()
2811 mpImpl
->handleDirectoryChanged();
2814 OUString
FileDialogHelper::HelpRequested( const FilePickerEvent
& aEvent
)
2816 return sfx2::FileDialogHelper_Impl::handleHelpRequested( aEvent
);
2819 void FileDialogHelper::ControlStateChanged( const FilePickerEvent
& aEvent
)
2821 mpImpl
->handleControlStateChanged( aEvent
);
2824 void FileDialogHelper::DialogSizeChanged()
2826 mpImpl
->handleDialogSizeChanged();
2829 void FileDialogHelper::DialogClosed( const DialogClosedEvent
& _rEvent
)
2831 m_nError
= ( RET_OK
== _rEvent
.DialogResult
) ? ERRCODE_NONE
: ERRCODE_ABORT
;
2832 m_aDialogClosedLink
.Call( this );
2835 ErrCode
FileOpenDialog_Impl( weld::Window
* pParent
,
2836 sal_Int16 nDialogType
,
2837 FileDialogFlags nFlags
,
2838 std::vector
<OUString
>& rpURLList
,
2840 std::optional
<SfxAllItemSet
>& rpSet
,
2841 const OUString
* pPath
,
2843 const OUString
& rStandardDir
,
2844 const css::uno::Sequence
< OUString
>& rDenyList
)
2847 std::unique_ptr
<FileDialogHelper
> pDialog
;
2848 // Sign existing PDF: only works with PDF files and they are opened
2849 // read-only to discourage editing (which would invalidate existing
2851 if (nFlags
& FileDialogFlags::SignPDF
)
2852 pDialog
.reset(new FileDialogHelper(nDialogType
, nFlags
, SfxResId(STR_SFX_FILTERNAME_PDF
), "pdf", rStandardDir
, rDenyList
, pParent
));
2854 pDialog
.reset(new FileDialogHelper(nDialogType
, nFlags
, OUString(), nDialog
, SfxFilterFlags::NONE
, SfxFilterFlags::NONE
, rStandardDir
, rDenyList
, pParent
));
2860 nRet
= pDialog
->Execute(rpURLList
, rpSet
, rFilter
, aPath
);
2861 DBG_ASSERT( rFilter
.indexOf(": ") == -1, "Old filter name used!");
2863 if (rpSet
&& nFlags
& FileDialogFlags::SignPDF
)
2864 rpSet
->Put(SfxBoolItem(SID_DOC_READONLY
, true));
2868 bool IsMSType(const std::shared_ptr
<const SfxFilter
>& pCurrentFilter
)
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 return !pCurrentFilter
->IsOwnFormat();
2875 bool IsOOXML(const std::shared_ptr
<const SfxFilter
>& pCurrentFilter
)
2877 // For OOXML we can use the standard password ("unlimited" characters)
2878 return IsMSType(pCurrentFilter
) && lclSupportsOOXMLEncryption( pCurrentFilter
->GetFilterName());
2881 ErrCode
SetPassword(const std::shared_ptr
<const SfxFilter
>& pCurrentFilter
, SfxItemSet
* pSet
,
2882 const OUString
& rPasswordToOpen
, const OUString
& rPasswordToModify
,
2883 bool bAllowPasswordReset
)
2885 const bool bMSType
= IsMSType(pCurrentFilter
);
2886 const bool bOOXML
= IsOOXML(pCurrentFilter
);
2888 if ( rPasswordToOpen
.getLength() )
2890 css::uno::Sequence
< css::beans::NamedValue
> aEncryptionData
;
2896 ::comphelper::SequenceAsHashMap aHashData
;
2897 aHashData
[ OUString( "OOXPassword" ) ] <<= rPasswordToOpen
;
2898 aHashData
[ OUString( "CryptoType" ) ] <<= OUString( "Standard" );
2899 aEncryptionData
= aHashData
.getAsConstNamedValueList();
2903 uno::Sequence
< sal_Int8
> aUniqueID
= ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 );
2904 uno::Sequence
< sal_Int8
> aEncryptionKey
= ::comphelper::DocPasswordHelper::GenerateStd97Key( rPasswordToOpen
, aUniqueID
);
2906 if ( aEncryptionKey
.hasElements() )
2908 ::comphelper::SequenceAsHashMap aHashData
;
2909 aHashData
[ OUString( "STD97EncryptionKey" ) ] <<= aEncryptionKey
;
2910 aHashData
[ OUString( "STD97UniqueID" ) ] <<= aUniqueID
;
2912 aEncryptionData
= aHashData
.getAsConstNamedValueList();
2916 return ERRCODE_IO_NOTSUPPORTED
;
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 pSet
->Put(SfxUnoAnyItem(
2925 uno::makeAny(comphelper::concatSequences(
2926 aEncryptionData
, comphelper::OStorageHelper::CreatePackageEncryptionData(
2927 rPasswordToOpen
)))));
2929 else if (bAllowPasswordReset
)
2933 if (pSet
->HasItem(SID_ENCRYPTIONDATA
))
2934 pSet
->ClearItem(SID_MODIFYPASSWORDINFO
);
2935 if (pSet
->HasItem(SID_ENCRYPTIONDATA
))
2936 pSet
->ClearItem(SID_ENCRYPTIONDATA
);
2938 return ERRCODE_NONE
;
2945 uno::Sequence
<beans::PropertyValue
> aModifyPasswordInfo
2946 = ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfoOOXML(
2948 if (aModifyPasswordInfo
.hasElements() && pSet
)
2950 SfxUnoAnyItem(SID_MODIFYPASSWORDINFO
, uno::makeAny(aModifyPasswordInfo
)));
2954 // the empty password has 0 as Hash
2955 sal_Int32 nHash
= SfxMedium::CreatePasswordToModifyHash(
2957 pCurrentFilter
->GetServiceName() == "com.sun.star.text.TextDocument");
2959 pSet
->Put(SfxUnoAnyItem(SID_MODIFYPASSWORDINFO
, uno::makeAny(nHash
)));
2964 uno::Sequence
< beans::PropertyValue
> aModifyPasswordInfo
= ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( rPasswordToModify
);
2965 if ( aModifyPasswordInfo
.hasElements() && pSet
)
2966 pSet
->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO
, uno::makeAny( aModifyPasswordInfo
) ) );
2968 return ERRCODE_NONE
;
2973 ErrCode
RequestPassword(const std::shared_ptr
<const SfxFilter
>& pCurrentFilter
, OUString
const & aURL
, SfxItemSet
* pSet
, const css::uno::Reference
<css::awt::XWindow
>& rParent
)
2975 uno::Reference
<task::XInteractionHandler2
> xInteractionHandler
= task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), rParent
);
2976 const auto eType
= IsMSType(pCurrentFilter
) && !IsOOXML(pCurrentFilter
) ?
2977 ::comphelper::DocPasswordRequestType::MS
:
2978 ::comphelper::DocPasswordRequestType::Standard
;
2980 ::rtl::Reference
< ::comphelper::DocPasswordRequest
> pPasswordRequest( new ::comphelper::DocPasswordRequest( eType
, css::task::PasswordRequestMode_PASSWORD_CREATE
, aURL
, bool( pCurrentFilter
->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY
) ) );
2982 const bool bMSType
= IsMSType(pCurrentFilter
);
2984 uno::Reference
< css::task::XInteractionRequest
> rRequest( pPasswordRequest
);
2987 xInteractionHandler
->handle( rRequest
);
2988 if (!pPasswordRequest
->isPassword() || bMSType
)
2992 OString
const utf8Pwd(OUStringToOString(pPasswordRequest
->getPassword(), RTL_TEXTENCODING_UTF8
));
2993 OString
const utf8Ptm(OUStringToOString(pPasswordRequest
->getPasswordToModify(), RTL_TEXTENCODING_UTF8
));
2994 if (!(52 <= utf8Pwd
.getLength() && utf8Pwd
.getLength() <= 55
2995 && GetODFSaneDefaultVersion() < SvtSaveOptions::ODFSVER_012
)
2996 && (52 > utf8Ptm
.getLength() || utf8Ptm
.getLength() > 55))
3000 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(Application::GetFrameWeld(rParent
), VclMessageType::Warning
,
3001 VclButtonsType::Ok
, SfxResId(STR_PASSWORD_LEN
)));
3002 xBox
->set_secondary_text(SfxResId(STR_PASSWORD_WARNING
));
3006 if ( !pPasswordRequest
->isPassword() )
3007 return ERRCODE_ABORT
;
3009 const auto result
= SetPassword(pCurrentFilter
, pSet
, pPasswordRequest
->getPassword(), pPasswordRequest
->getPasswordToModify());
3011 if ( result
!= ERRCODE_IO_NOTSUPPORTED
&& pPasswordRequest
->getRecommendReadOnly() )
3012 pSet
->Put( SfxBoolItem( SID_RECOMMENDREADONLY
, true ) );
3017 OUString
EncodeSpaces_Impl( const OUString
& rSource
)
3019 OUString sRet
= rSource
.replaceAll( " ", "%20" );
3023 OUString
DecodeSpaces_Impl( const OUString
& rSource
)
3025 OUString sRet
= rSource
.replaceAll( "%20", " " );
3029 } // end of namespace sfx2
3031 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */