Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/doc/docinsert.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 <sfx2/app.hxx>
21
#include <sfx2/docinsert.hxx>
22
#include <sfx2/docfile.hxx>
23
#include <sfx2/fcontnr.hxx>
24
#include <sfx2/filedlghelper.hxx>
25
#include <appopen.hxx>
26
#include <openflag.hxx>
27
#include <sfx2/passwd.hxx>
28
29
#include <sfx2/sfxsids.hrc>
30
#include <com/sun/star/ui/dialogs/ControlActions.hpp>
31
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
32
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
33
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
34
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
35
#include <com/sun/star/lang/IllegalArgumentException.hpp>
36
#include <tools/debug.hxx>
37
#include <tools/urlobj.hxx>
38
#include <svl/itemset.hxx>
39
#include <svl/eitem.hxx>
40
#include <svl/intitem.hxx>
41
#include <svl/stritem.hxx>
42
#include <vcl/vclenum.hxx>
43
#include <memory>
44
#include <utility>
45
#include <comphelper/diagnose_ex.hxx>
46
47
using namespace ::com::sun::star;
48
using namespace ::com::sun::star::lang;
49
using namespace ::com::sun::star::ui::dialogs;
50
using namespace ::com::sun::star::uno;
51
52
namespace
53
{
54
55
FileDialogFlags lcl_map_mode_to_flags(const sfx2::DocumentInserter::Mode mode)
56
0
{
57
0
    FileDialogFlags f {FileDialogFlags::NONE};
58
0
    switch (mode)
59
0
    {
60
0
        case sfx2::DocumentInserter::Mode::Insert:
61
0
            f = FileDialogFlags::Insert;
62
0
            break;
63
0
        case sfx2::DocumentInserter::Mode::InsertMulti:
64
0
            f = FileDialogFlags::Insert|FileDialogFlags::MultiSelection;
65
0
            break;
66
0
        case sfx2::DocumentInserter::Mode::Compare:
67
0
            f = FileDialogFlags::InsertCompare;
68
0
            break;
69
0
        case sfx2::DocumentInserter::Mode::Merge:
70
0
            f = FileDialogFlags::InsertMerge;
71
0
            break;
72
0
    }
73
0
    return f;
74
0
}
75
76
}
77
78
namespace sfx2 {
79
80
DocumentInserter::DocumentInserter(weld::Window* pParent, OUString sFactory, const Mode mode)
81
0
    : m_pParent                 ( pParent )
82
0
    , m_sDocFactory             (std::move( sFactory ))
83
0
    , m_nDlgFlags               ( lcl_map_mode_to_flags(mode) )
84
0
    , m_nError                  ( ERRCODE_NONE )
85
0
{
86
0
}
87
88
DocumentInserter::~DocumentInserter()
89
0
{
90
0
}
91
92
void DocumentInserter::StartExecuteModal( const Link<sfx2::FileDialogHelper*,void>& _rDialogClosedLink )
93
0
{
94
0
    m_aDialogClosedLink = _rDialogClosedLink;
95
0
    m_nError = ERRCODE_NONE;
96
0
    if ( !m_pFileDlg )
97
0
    {
98
0
        m_pFileDlg.reset( new FileDialogHelper(
99
0
                ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
100
0
                m_nDlgFlags, m_sDocFactory, SfxFilterFlags::NONE, SfxFilterFlags::NONE, m_pParent ) );
101
0
    }
102
0
    m_pFileDlg->SetContext(FileDialogHelper::InsertDoc);
103
0
    m_pFileDlg->StartExecuteModal( LINK( this, DocumentInserter, DialogClosedHdl ) );
104
0
}
105
106
std::unique_ptr<SfxMedium> DocumentInserter::CreateMedium(char const*const pFallbackHack)
107
0
{
108
0
    std::unique_ptr<SfxMedium> pMedium;
109
0
    if (!m_nError && m_xItemSet && !m_pURLList.empty())
110
0
    {
111
0
        DBG_ASSERT( m_pURLList.size() == 1, "DocumentInserter::CreateMedium(): invalid URL list count" );
112
0
        pMedium.reset(new SfxMedium(
113
0
                m_pURLList[0], SFX_STREAM_READONLY,
114
0
                SfxGetpApp()->GetFilterMatcher().GetFilter4FilterName( m_sFilter ), m_xItemSet ));
115
0
        pMedium->UseInteractionHandler( true );
116
0
        std::optional<SfxFilterMatcher> pMatcher;
117
0
        if ( !m_sDocFactory.isEmpty() )
118
0
            pMatcher.emplace(m_sDocFactory);
119
0
        else
120
0
            pMatcher.emplace();
121
122
0
        std::shared_ptr<const SfxFilter> pFilter;
123
0
        ErrCode nError = pMatcher->DetectFilter( *pMedium, pFilter );
124
        // tdf#101813 hack: check again if it's a global document
125
0
        if (ERRCODE_NONE != nError && pFallbackHack)
126
0
        {
127
0
            pMatcher.emplace(OUString::createFromAscii(pFallbackHack));
128
0
            nError = pMatcher->DetectFilter( *pMedium, pFilter );
129
0
        }
130
0
        if ( nError == ERRCODE_NONE && pFilter )
131
0
            pMedium->SetFilter( pFilter );
132
0
        else
133
0
            pMedium.reset();
134
135
0
        if ( pMedium && CheckPasswd_Impl( nullptr, pMedium.get() ) == ERRCODE_ABORT )
136
0
            pMedium.reset();
137
0
    }
138
139
0
    return pMedium;
140
0
}
141
142
SfxMediumList DocumentInserter::CreateMediumList()
143
0
{
144
0
    SfxMediumList aMediumList;
145
0
    if (!m_nError && m_xItemSet && !m_pURLList.empty())
146
0
    {
147
0
        for (auto const& url : m_pURLList)
148
0
        {
149
0
            std::unique_ptr<SfxMedium> pMedium(new SfxMedium(
150
0
                    url, SFX_STREAM_READONLY,
151
0
                    SfxGetpApp()->GetFilterMatcher().GetFilter4FilterName( m_sFilter ), m_xItemSet ));
152
153
0
            pMedium->UseInteractionHandler( true );
154
155
0
            SfxFilterMatcher aMatcher( m_sDocFactory );
156
0
            std::shared_ptr<const SfxFilter> pFilter;
157
0
            ErrCode nError = aMatcher.DetectFilter( *pMedium, pFilter );
158
0
            if ( nError == ERRCODE_NONE && pFilter )
159
0
                pMedium->SetFilter( pFilter );
160
0
            else
161
0
                pMedium.reset();
162
163
0
            if( pMedium && CheckPasswd_Impl( nullptr, pMedium.get() ) != ERRCODE_ABORT )
164
0
                aMediumList.push_back( std::move(pMedium) );
165
0
        }
166
0
    }
167
168
0
    return aMediumList;
169
0
}
170
171
static void impl_FillURLList( sfx2::FileDialogHelper const * _pFileDlg, std::vector<OUString>& _rpURLList )
172
0
{
173
0
    assert(_pFileDlg && "DocumentInserter::fillURLList(): invalid file dialog");
174
175
0
    const Sequence < OUString > aPathSeq = _pFileDlg->GetSelectedFiles();
176
177
0
    if ( aPathSeq.hasElements() )
178
0
    {
179
0
        _rpURLList.clear();
180
181
0
        std::transform(aPathSeq.begin(), aPathSeq.end(), std::back_inserter(_rpURLList),
182
0
            [](const OUString& rPath) -> OUString {
183
0
                INetURLObject aPathObj( rPath );
184
0
                return aPathObj.GetMainURL(INetURLObject::DecodeMechanism::NONE);
185
0
            });
186
0
    }
187
0
}
188
189
IMPL_LINK_NOARG(DocumentInserter, DialogClosedHdl, sfx2::FileDialogHelper*, void)
190
0
{
191
0
    DBG_ASSERT( m_pFileDlg, "DocumentInserter::DialogClosedHdl(): no file dialog" );
192
193
0
    m_nError = m_pFileDlg->GetError();
194
0
    if ( ERRCODE_NONE == m_nError )
195
0
        impl_FillURLList( m_pFileDlg.get(), m_pURLList );
196
197
0
    Reference < XFilePicker3 > xFP = m_pFileDlg->GetFilePicker();
198
0
    Reference < XFilePickerControlAccess > xCtrlAccess( xFP, UNO_QUERY );
199
0
    if ( xCtrlAccess.is() )
200
0
    {
201
        // always create a new itemset
202
0
        m_xItemSet = std::make_shared<SfxAllItemSet>( SfxGetpApp()->GetPool() );
203
204
0
        short nDlgType = m_pFileDlg->GetDialogType();
205
0
        bool bHasPassword = (
206
0
               TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD == nDlgType
207
0
            || TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS == nDlgType );
208
209
        // check, whether or not we have to display a password box
210
0
        if ( bHasPassword && m_pFileDlg->IsPasswordEnabled() )
211
0
        {
212
0
            try
213
0
            {
214
0
                Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 );
215
0
                bool bPassWord = false;
216
0
                if ( ( aValue >>= bPassWord ) && bPassWord )
217
0
                {
218
                    // ask for the password
219
0
                    SfxPasswordDialog aPasswordDlg(m_pParent);
220
0
                    aPasswordDlg.ShowExtras( SfxShowExtras::CONFIRM );
221
0
                    short nRet = aPasswordDlg.run();
222
0
                    if ( RET_OK == nRet )
223
0
                    {
224
0
                        m_xItemSet->Put( SfxStringItem( SID_PASSWORD, aPasswordDlg.GetPassword() ) );
225
0
                    }
226
0
                    else
227
0
                    {
228
0
                        m_xItemSet.reset();
229
0
                        return;
230
0
                    }
231
0
                }
232
0
            }
233
0
            catch( const IllegalArgumentException& ){}
234
0
        }
235
236
0
        if ( m_nDlgFlags & FileDialogFlags::Export )
237
0
        {
238
0
            try
239
0
            {
240
0
                Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 );
241
0
                bool bSelection = false;
242
0
                if ( aValue >>= bSelection )
243
0
                    m_xItemSet->Put( SfxBoolItem( SID_SELECTION, bSelection ) );
244
0
            }
245
0
            catch( const IllegalArgumentException& )
246
0
            {
247
0
                TOOLS_WARN_EXCEPTION( "sfx.doc", "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
248
0
            }
249
0
        }
250
251
252
        // set the read-only flag. When inserting a file, this flag is always set
253
0
        if ( m_nDlgFlags & FileDialogFlags::Insert )
254
0
            m_xItemSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
255
0
        else
256
0
        {
257
0
            if ( TemplateDescription::FILEOPEN_READONLY_VERSION == nDlgType )
258
0
            {
259
0
                try
260
0
                {
261
0
                    Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 );
262
0
                    bool bReadOnly = false;
263
0
                    if ( ( aValue >>= bReadOnly ) && bReadOnly )
264
0
                        m_xItemSet->Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) );
265
0
                }
266
0
                catch( const IllegalArgumentException& )
267
0
                {
268
0
                    TOOLS_WARN_EXCEPTION( "sfx.doc", "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" );
269
0
                }
270
0
            }
271
0
        }
272
273
0
        if ( TemplateDescription::FILEOPEN_READONLY_VERSION == nDlgType )
274
0
        {
275
0
            try
276
0
            {
277
0
                Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION,
278
0
                                                    ControlActions::GET_SELECTED_ITEM_INDEX );
279
0
                sal_Int32 nVersion = 0;
280
0
                if ( ( aValue >>= nVersion ) && nVersion > 0 )
281
                    // open a special version; 0 == current version
282
0
                    m_xItemSet->Put( SfxInt16Item( SID_VERSION, static_cast<short>(nVersion) ) );
283
0
            }
284
0
            catch( const IllegalArgumentException& ){}
285
0
        }
286
0
    }
287
288
0
    m_sFilter = m_pFileDlg->GetRealFilter();
289
290
0
    m_aDialogClosedLink.Call( m_pFileDlg.get() );
291
0
}
292
293
} // namespace sfx2
294
295
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */