Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/bastyp/fltfnc.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
21
#include <com/sun/star/uno/Exception.hpp>
22
#include <com/sun/star/beans/PropertyValue.hpp>
23
#include <com/sun/star/beans/NamedValue.hpp>
24
#include <com/sun/star/container/XNameAccess.hpp>
25
#include <com/sun/star/container/XEnumeration.hpp>
26
#include <com/sun/star/document/XTypeDetection.hpp>
27
#include <com/sun/star/container/XContainerQuery.hpp>
28
#include <com/sun/star/io/XInputStream.hpp>
29
#include <com/sun/star/task/XInteractionHandler.hpp>
30
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
31
32
#include <comphelper/sequenceashashmap.hxx>
33
34
#include <sot/exchange.hxx>
35
#include <utility>
36
#include <vcl/svapp.hxx>
37
#include <vcl/weld/weld.hxx>
38
#include <rtl/ustring.hxx>
39
#include <rtl/ustrbuf.hxx>
40
#include <sal/log.hxx>
41
#include <svl/stritem.hxx>
42
43
#include <comphelper/processfactory.hxx>
44
45
#include <sal/types.h>
46
#include <com/sun/star/uno/Reference.hxx>
47
#include <unotools/moduleoptions.hxx>
48
#include <unotools/mediadescriptor.hxx>
49
#include <tools/urlobj.hxx>
50
51
#include <unotools/syslocale.hxx>
52
#include <unotools/charclass.hxx>
53
54
#include <sfx2/docfilt.hxx>
55
#include <sfx2/fcontnr.hxx>
56
#include <sfxtypes.hxx>
57
#include <sfx2/docfile.hxx>
58
#include <sfx2/strings.hrc>
59
#include <sfx2/sfxresid.hxx>
60
#include <sfx2/objsh.hxx>
61
#include <sfx2/sfxsids.hrc>
62
#include "fltlst.hxx"
63
#include <arrdecl.hxx>
64
65
#include <vector>
66
#include <memory>
67
68
#if defined(DBG_UTIL)
69
unsigned SfxStack::nLevel = 0;
70
#endif
71
72
using namespace com::sun::star;
73
74
static SfxFilterList_Impl* pFilterArr = nullptr;
75
static bool bFirstRead = true;
76
77
static void CreateFilterArr()
78
0
{
79
0
    static SfxFilterList_Impl theSfxFilterArray;
80
0
    pFilterArr = &theSfxFilterArray;
81
0
    static SfxFilterListener theSfxFilterListener;
82
0
}
83
84
static OUString ToUpper_Impl( const OUString &rStr )
85
0
{
86
0
    return SvtSysLocale().GetCharClass().uppercase( rStr );
87
0
}
88
89
class SfxFilterContainer_Impl
90
{
91
public:
92
    OUString            aName;
93
94
    explicit SfxFilterContainer_Impl( OUString _aName )
95
46
        : aName(std::move( _aName ))
96
46
    {
97
46
    }
98
};
99
100
std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4EA(const OUString& rEA, SfxFilterFlags nMust, SfxFilterFlags nDont) const
101
0
{
102
0
    SfxFilterMatcher aMatch(pImpl->aName);
103
0
    return aMatch.GetFilter4EA(rEA, nMust, nDont);
104
0
}
105
106
std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4Extension(const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont) const
107
0
{
108
0
    SfxFilterMatcher aMatch(pImpl->aName);
109
0
    return aMatch.GetFilter4Extension(rExt, nMust, nDont);
110
0
}
111
112
std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4FilterName(const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont) const
113
0
{
114
0
    SfxFilterMatcher aMatch(pImpl->aName);
115
0
    return aMatch.GetFilter4FilterName(rName, nMust, nDont);
116
0
}
117
118
std::shared_ptr<const SfxFilter> SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
119
0
{
120
0
    SfxFilterMatcher aMatch( pImpl->aName );
121
0
    return aMatch.GetAnyFilter( nMust, nDont );
122
0
}
123
124
125
SfxFilterContainer::SfxFilterContainer( const OUString& rName )
126
46
   : pImpl( new SfxFilterContainer_Impl( rName ) )
127
46
{
128
46
}
129
130
131
SfxFilterContainer::~SfxFilterContainer()
132
46
{
133
46
}
134
135
136
OUString const & SfxFilterContainer::GetName() const
137
0
{
138
0
    return pImpl->aName;
139
0
}
140
141
std::shared_ptr<const SfxFilter> SfxFilterContainer::GetDefaultFilter_Impl( std::u16string_view rName )
142
0
{
143
    // Try to find out the type of factory.
144
    // Interpret given name as Service- and ShortName!
145
0
    SvtModuleOptions aOpt;
146
0
    SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByServiceName(rName);
147
0
    if (eFactory == SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
148
0
        eFactory = SvtModuleOptions::ClassifyFactoryByShortName(rName);
149
150
    // could not classify factory by its service nor by its short name.
151
    // Must be an unknown factory! => return NULL
152
0
    if (eFactory == SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
153
0
        return nullptr;
154
155
    // For the following code we need some additional information.
156
0
    const OUString& sServiceName   = aOpt.GetFactoryName(eFactory);
157
0
    OUString sDefaultFilter = aOpt.GetFactoryDefaultFilter(eFactory);
158
159
    // Try to get the default filter. Don't forget to verify it.
160
    // May the set default filter does not exists any longer or
161
    // does not fit the given factory.
162
0
    const SfxFilterMatcher aMatcher;
163
0
    std::shared_ptr<const SfxFilter> pFilter = aMatcher.GetFilter4FilterName(sDefaultFilter);
164
165
0
    if (
166
0
        pFilter &&
167
0
        !pFilter->GetServiceName().equalsIgnoreAsciiCase(sServiceName)
168
0
       )
169
0
    {
170
0
        pFilter = nullptr;
171
0
    }
172
173
    // If at least no default filter could be located - use any filter of this
174
    // factory.
175
0
    if (!pFilter)
176
0
    {
177
0
        if ( bFirstRead )
178
0
            ReadFilters_Impl();
179
180
0
        for (const std::shared_ptr<const SfxFilter>& pCheckFilter : *pFilterArr)
181
0
        {
182
0
            if ( pCheckFilter->GetServiceName().equalsIgnoreAsciiCase(sServiceName) )
183
0
            {
184
0
                pFilter = pCheckFilter;
185
0
                break;
186
0
            }
187
0
        }
188
0
    }
189
190
0
    return pFilter;
191
0
}
192
193
194
// Impl-Data is shared between all FilterMatchers of the same factory
195
class SfxFilterMatcher_Impl
196
{
197
public:
198
    OUString                    aName;
199
    mutable SfxFilterList_Impl* pList;      // is created on demand
200
201
    void InitForIterating() const;
202
    void Update() const;
203
    explicit SfxFilterMatcher_Impl(OUString _aName)
204
0
        : aName(std::move(_aName))
205
0
        , pList(nullptr)
206
0
    {
207
0
    }
208
    ~SfxFilterMatcher_Impl()
209
0
    {
210
        // SfxFilterMatcher_Impl::InitForIterating() will set pList to
211
        // either the global filter array matcher pFilterArr, or to
212
        // a new SfxFilterList_Impl.
213
0
        if (pList != pFilterArr)
214
0
            delete pList;
215
0
    }
216
};
217
218
namespace
219
{
220
    std::vector<std::unique_ptr<SfxFilterMatcher_Impl> > aImplArr;
221
    int nSfxFilterMatcherCount;
222
223
    SfxFilterMatcher_Impl & getSfxFilterMatcher_Impl(const OUString &rName)
224
0
    {
225
0
        OUString aName;
226
227
0
        if (!rName.isEmpty())
228
0
            aName = SfxObjectShell::GetServiceNameFromFactory(rName);
229
230
        // find the impl-Data of any comparable FilterMatcher that was created
231
        // previously
232
0
        for (std::unique_ptr<SfxFilterMatcher_Impl>& aImpl : aImplArr)
233
0
            if (aImpl->aName == aName)
234
0
                return *aImpl;
235
236
        // first Matcher created for this factory
237
0
        aImplArr.push_back(std::make_unique<SfxFilterMatcher_Impl>(aName));
238
0
        return *aImplArr.back();
239
0
    }
240
}
241
242
SfxFilterMatcher::SfxFilterMatcher( const OUString& rName )
243
0
    : m_rImpl( getSfxFilterMatcher_Impl(rName) )
244
0
{
245
0
    ++nSfxFilterMatcherCount;
246
0
}
247
248
SfxFilterMatcher::SfxFilterMatcher()
249
0
    : m_rImpl( getSfxFilterMatcher_Impl(OUString()) )
250
0
{
251
    // global FilterMatcher always uses global filter array (also created on
252
    // demand)
253
0
    ++nSfxFilterMatcherCount;
254
0
}
255
256
SfxFilterMatcher::~SfxFilterMatcher()
257
0
{
258
0
    --nSfxFilterMatcherCount;
259
0
    if (nSfxFilterMatcherCount == 0)
260
0
        aImplArr.clear();
261
0
}
262
263
void SfxFilterMatcher_Impl::Update() const
264
0
{
265
0
    if ( pList )
266
0
    {
267
        // this List was already used
268
0
        pList->clear();
269
0
        for (const std::shared_ptr<const SfxFilter>& pFilter : *pFilterArr)
270
0
        {
271
0
            if ( pFilter->GetServiceName() == aName )
272
0
                pList->push_back( pFilter );
273
0
        }
274
0
    }
275
0
}
276
277
void SfxFilterMatcher_Impl::InitForIterating() const
278
0
{
279
0
    if ( pList )
280
0
        return;
281
282
0
    if ( bFirstRead )
283
        // global filter array has not been created yet
284
0
        SfxFilterContainer::ReadFilters_Impl();
285
286
0
    if ( !aName.isEmpty() )
287
0
    {
288
        // matcher of factory: use only filters of that document type
289
0
        pList = new SfxFilterList_Impl;
290
0
        Update();
291
0
    }
292
0
    else
293
0
    {
294
        // global matcher: use global filter array
295
0
        pList = pFilterArr;
296
0
    }
297
0
}
298
299
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
300
0
{
301
0
    m_rImpl.InitForIterating();
302
0
    for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
303
0
    {
304
0
        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
305
0
        if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) )
306
0
            return pFilter;
307
0
    }
308
309
0
    return nullptr;
310
0
}
311
312
313
ErrCode  SfxFilterMatcher::GuessFilterIgnoringContent(
314
    SfxMedium const & rMedium,
315
    std::shared_ptr<const SfxFilter>& rpFilter ) const
316
0
{
317
0
    uno::Reference<document::XTypeDetection> xDetection(
318
0
        comphelper::getProcessServiceFactory()->createInstance(u"com.sun.star.document.TypeDetection"_ustr), uno::UNO_QUERY);
319
320
0
    OUString sTypeName;
321
0
    try
322
0
    {
323
0
        sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
324
0
    }
325
0
    catch (uno::Exception&)
326
0
    {
327
0
    }
328
329
0
    rpFilter = nullptr;
330
0
    if ( !sTypeName.isEmpty() )
331
0
    {
332
        // make sure filter list is initialized
333
0
        m_rImpl.InitForIterating();
334
0
        rpFilter = GetFilter4EA( sTypeName );
335
0
    }
336
337
0
    return rpFilter ? ERRCODE_NONE : ERRCODE_ABORT;
338
0
}
339
340
341
ErrCode  SfxFilterMatcher::GuessFilter( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
342
0
{
343
0
    return GuessFilterControlDefaultUI( rMedium, rpFilter, nMust, nDont );
344
0
}
345
346
347
ErrCode  SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
348
0
{
349
0
    std::shared_ptr<const SfxFilter> pOldFilter = rpFilter;
350
351
    // no detection service -> nothing to do !
352
0
    uno::Reference<document::XTypeDetection> xDetection(
353
0
        comphelper::getProcessServiceFactory()->createInstance(u"com.sun.star.document.TypeDetection"_ustr), uno::UNO_QUERY);
354
355
0
    if (!xDetection.is())
356
0
        return ERRCODE_ABORT;
357
358
0
    try
359
0
    {
360
        // open the stream one times only ...
361
        // Otherwise it will be tried more than once and show the same interaction more than once ...
362
363
0
        OUString sURL( rMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
364
0
        uno::Reference< io::XInputStream > xInStream = rMedium.GetInputStream();
365
0
        OUString aFilterName;
366
0
        OUString sTypeName;
367
368
        // stream exists => deep detection (with preselection ... if possible)
369
0
        if (xInStream.is())
370
0
        {
371
0
            comphelper::SequenceAsHashMap aDescriptor;
372
373
0
            aDescriptor[utl::MediaDescriptor::PROP_URL               ] <<= sURL;
374
0
            aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM       ] <<= xInStream;
375
0
            aDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<= rMedium.GetInteractionHandler();
376
0
            SfxStringItem const * it = rMedium.GetItemSet().GetItem(SID_REFERER);
377
0
            if (it != nullptr) {
378
0
                aDescriptor[utl::MediaDescriptor::PROP_REFERRER]
379
0
                    <<= it->GetValue();
380
0
            }
381
382
0
            if ( !m_rImpl.aName.isEmpty() )
383
0
                aDescriptor[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] <<= m_rImpl.aName;
384
385
0
            if ( pOldFilter )
386
0
            {
387
0
                aDescriptor[utl::MediaDescriptor::PROP_TYPENAME  ] <<= pOldFilter->GetTypeName();
388
0
                aDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= pOldFilter->GetFilterName();
389
0
            }
390
391
0
            uno::Sequence< beans::PropertyValue > lDescriptor = aDescriptor.getAsConstPropertyValueList();
392
0
            sTypeName = xDetection->queryTypeByDescriptor(lDescriptor, true); // lDescriptor is used as In/Out param ... don't use aDescriptor.getAsConstPropertyValueList() directly!
393
394
0
            for (const auto& rProp : lDescriptor)
395
0
            {
396
0
                if (rProp.Name == "FilterName")
397
                    // Type detection picked a preferred filter for this format.
398
0
                    aFilterName = rProp.Value.get<OUString>();
399
0
            }
400
0
        }
401
        // no stream exists => try flat detection without preselection as fallback
402
0
        else
403
0
            sTypeName = xDetection->queryTypeByURL(sURL);
404
405
0
        if (!sTypeName.isEmpty())
406
0
        {
407
0
            std::shared_ptr<const SfxFilter> xNewFilter;
408
0
            if (!aFilterName.isEmpty())
409
                // Type detection returned a suitable filter for this.  Use it.
410
0
                xNewFilter = SfxFilter::GetFilterByName(aFilterName);
411
412
            // fdo#78742 respect requested document service if set
413
0
            if (!xNewFilter || (!m_rImpl.aName.isEmpty()
414
0
                             && m_rImpl.aName != xNewFilter->GetServiceName()))
415
0
            {
416
                // detect filter by given type
417
                // In case of this matcher is bound to a particular document type:
418
                // If there is no acceptable type for this document at all, the type detection has possibly returned something else.
419
                // The DocumentService property is only a preselection, and all preselections are considered as optional!
420
                // This "wrong" type will be sorted out now because we match only allowed filters to the detected type
421
0
                uno::Sequence< beans::NamedValue > lQuery { { u"Name"_ustr, css::uno::Any(sTypeName) } };
422
423
0
                xNewFilter = GetFilterForProps(lQuery, nMust, nDont);
424
0
                if (xNewFilter && xNewFilter->GetFilterName().endsWith("_pdf_addstream_import")
425
0
                    && aFilterName.endsWith("_pdf_import")
426
0
                    && sTypeName == "pdf_Portable_Document_Format")
427
0
                {
428
                    // pdf_Portable_Document_Format covers two sets of import filters: normal PDF
429
                    // (like draw_pdf_import), and hybrid (like calc_pdf_addstream_import).
430
                    // Type detection didn't detect hybrid PDF; this new filter can't match
431
0
                    xNewFilter.reset();
432
0
                }
433
0
            }
434
435
0
            if (xNewFilter)
436
0
            {
437
0
                rpFilter = std::move(xNewFilter);
438
0
                return ERRCODE_NONE;
439
0
            }
440
0
        }
441
0
    }
442
0
    catch (const uno::Exception&)
443
0
    {}
444
445
0
    return ERRCODE_ABORT;
446
0
}
447
448
449
bool SfxFilterMatcher::IsFilterInstalled_Impl( const std::shared_ptr<const SfxFilter>& pFilter )
450
0
{
451
0
    if ( pFilter->GetFilterFlags() & SfxFilterFlags::MUSTINSTALL )
452
0
    {
453
        // Here could a  re-installation be offered
454
0
        OUString aText( SfxResId(STR_FILTER_NOT_INSTALLED) );
455
0
        aText = aText.replaceFirst( "$(FILTER)", pFilter->GetUIName() );
456
0
        std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
457
0
                                                       VclMessageType::Question, VclButtonsType::YesNo,
458
0
                                                       aText));
459
0
        xQueryBox->set_default_response(RET_YES);
460
461
0
        short nRet = xQueryBox->run();
462
0
        if ( nRet == RET_YES )
463
0
        {
464
#ifdef DBG_UTIL
465
            // Start Setup
466
            std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
467
                                                          VclMessageType::Info, VclButtonsType::Ok,
468
                                                          u"Here should the Setup now be starting!"_ustr));
469
            xInfoBox->run();
470
#endif
471
            // Installation must still give feedback if it worked or not,
472
            // then the  Filterflag be deleted
473
0
        }
474
475
0
        return ( !(pFilter->GetFilterFlags() & SfxFilterFlags::MUSTINSTALL) );
476
0
    }
477
0
    else if ( pFilter->GetFilterFlags() & SfxFilterFlags::CONSULTSERVICE )
478
0
    {
479
0
        OUString aText( SfxResId(STR_FILTER_CONSULT_SERVICE) );
480
0
        aText = aText.replaceFirst( "$(FILTER)", pFilter->GetUIName() );
481
0
        std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
482
0
                                                      VclMessageType::Info, VclButtonsType::Ok,
483
0
                                                      aText));
484
0
        xInfoBox->run();
485
0
        return false;
486
0
    }
487
0
    else
488
0
        return true;
489
0
}
490
491
492
ErrCode SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter ) const
493
/*  [Description]
494
495
    Here the Filter selection box is pulled up. Otherwise GuessFilter
496
 */
497
498
0
{
499
0
    std::shared_ptr<const SfxFilter> pFilter = rMedium.GetFilter();
500
0
    if ( pFilter )
501
0
    {
502
0
        if( !IsFilterInstalled_Impl( pFilter ) )
503
0
            pFilter = nullptr;
504
0
        else
505
0
        {
506
0
            const SfxStringItem* pSalvageItem = rMedium.GetItemSet().GetItem(SID_DOC_SALVAGE, false);
507
0
            if ( ( pFilter->GetFilterFlags() & SfxFilterFlags::PACKED ) && pSalvageItem )
508
                // Salvage is always done without packing
509
0
                pFilter = nullptr;
510
0
        }
511
0
    }
512
513
0
    bool bPreview = rMedium.IsPreview_Impl();
514
0
    const SfxStringItem* pReferer = rMedium.GetItemSet().GetItem(SID_REFERER, false);
515
0
    if ( bPreview && rMedium.IsRemote() && ( !pReferer || !pReferer->GetValue().match("private:searchfolder:") ) )
516
0
        return ERRCODE_ABORT;
517
518
0
    ErrCode nErr = GuessFilter( rMedium, pFilter );
519
0
    if ( nErr == ERRCODE_ABORT )
520
0
        return nErr;
521
522
0
    if ( nErr == ERRCODE_IO_PENDING )
523
0
    {
524
0
        rpFilter = std::move(pFilter);
525
0
        return nErr;
526
0
    }
527
528
0
    if ( !pFilter )
529
0
    {
530
0
        std::shared_ptr<const SfxFilter> pInstallFilter;
531
532
        // Now test the filter which are not installed (ErrCode is irrelevant)
533
0
        GuessFilter( rMedium, pInstallFilter, SfxFilterFlags::IMPORT, SfxFilterFlags::CONSULTSERVICE );
534
0
        if ( pInstallFilter )
535
0
        {
536
0
            if ( IsFilterInstalled_Impl( pInstallFilter ) )
537
0
            {
538
                // Maybe the filter was installed afterwards.
539
0
                pFilter = std::move(pInstallFilter);
540
0
            }
541
0
        }
542
0
        else
543
0
        {
544
          // Now test the filter, which first must be obtained by Star
545
          // (ErrCode is irrelevant)
546
0
            GuessFilter( rMedium, pInstallFilter, SfxFilterFlags::IMPORT, SfxFilterFlags::NONE );
547
0
            if ( pInstallFilter )
548
0
                IsFilterInstalled_Impl( pInstallFilter );
549
0
        }
550
0
    }
551
552
0
    bool bHidden = bPreview;
553
0
    const SfxStringItem* pFlags = rMedium.GetItemSet().GetItem(SID_OPTIONS, false);
554
0
    if ( !bHidden && pFlags )
555
0
    {
556
0
        OUString aFlags( pFlags->GetValue() );
557
0
        aFlags = aFlags.toAsciiUpperCase();
558
0
        if( -1 != aFlags.indexOf( 'H' ) )
559
0
            bHidden = true;
560
0
    }
561
0
    rpFilter = pFilter;
562
563
0
    if ( bHidden )
564
0
        nErr = pFilter ? ERRCODE_NONE : ERRCODE_ABORT;
565
0
    return nErr;
566
0
}
567
568
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilterForProps( const css::uno::Sequence < beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
569
0
{
570
0
    uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
571
0
    if( !xServiceManager )
572
0
        return nullptr;
573
574
0
    static constexpr OUStringLiteral sTypeDetection = u"com.sun.star.document.TypeDetection";
575
0
    uno::Reference< container::XContainerQuery > xTypeCFG( xServiceManager->createInstance( sTypeDetection ), uno::UNO_QUERY );
576
0
    if ( !xTypeCFG )
577
0
        return nullptr;
578
579
    // make query for all types matching the properties
580
0
    uno::Reference < css::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
581
0
    uno::Sequence<beans::PropertyValue> aProps;
582
0
    while ( xEnum->hasMoreElements() )
583
0
    {
584
0
        static constexpr OUStringLiteral sPreferredFilter = u"PreferredFilter";
585
0
        static constexpr OUStringLiteral sName = u"Name";
586
587
0
        xEnum->nextElement() >>= aProps;
588
0
        OUString aValue, aName;
589
0
        for( const auto & rPropVal : aProps)
590
0
        {
591
0
            if (rPropVal.Name == sPreferredFilter)
592
0
                rPropVal.Value >>= aValue;
593
0
            else if (rPropVal.Name == sName)
594
0
                rPropVal.Value >>= aName;
595
0
        }
596
597
        // try to get the preferred filter (works without loading all filters!)
598
0
        if ( !aValue.isEmpty() )
599
0
        {
600
0
            std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName( aValue );
601
0
            if ( !pFilter || (pFilter->GetFilterFlags() & nMust) != nMust || (pFilter->GetFilterFlags() & nDont ) )
602
                // check for filter flags
603
                // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed
604
0
                continue;
605
606
0
            if ( !m_rImpl.aName.isEmpty() )
607
0
            {
608
                // if this is not the global FilterMatcher: check if filter matches the document type
609
0
                if ( pFilter->GetServiceName() != m_rImpl.aName )
610
0
                {
611
                    // preferred filter belongs to another document type; now we must search the filter
612
0
                    m_rImpl.InitForIterating();
613
0
                    pFilter = GetFilter4EA( aName, nMust, nDont );
614
0
                    if ( pFilter )
615
0
                        return pFilter;
616
0
                }
617
0
                else
618
0
                    return pFilter;
619
0
            }
620
0
            else
621
0
                return pFilter;
622
0
        }
623
0
    }
624
625
0
    return nullptr;
626
0
}
627
628
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4Mime( const OUString& rMediaType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
629
0
{
630
0
    if ( m_rImpl.pList )
631
0
    {
632
0
        for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
633
0
        {
634
0
            SfxFilterFlags nFlags = pFilter->GetFilterFlags();
635
0
            if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetMimeType() == rMediaType )
636
0
                return pFilter;
637
0
        }
638
639
0
        return nullptr;
640
0
    }
641
642
0
    css::uno::Sequence < css::beans::NamedValue > aSeq { { u"MediaType"_ustr, css::uno::Any(rMediaType) } };
643
0
    return GetFilterForProps( aSeq, nMust, nDont );
644
0
}
645
646
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4EA( const OUString& rType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
647
0
{
648
0
    if ( m_rImpl.pList )
649
0
    {
650
0
        std::shared_ptr<const SfxFilter> pFirst;
651
0
        for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
652
0
        {
653
0
            SfxFilterFlags nFlags = pFilter->GetFilterFlags();
654
0
            if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetTypeName() == rType )
655
0
            {
656
0
                if (nFlags & SfxFilterFlags::PREFERED)
657
0
                    return pFilter;
658
0
                if (!pFirst)
659
0
                    pFirst = pFilter;
660
0
            }
661
0
        }
662
0
        if (pFirst)
663
0
            return pFirst;
664
665
0
        return nullptr;
666
0
    }
667
668
0
    css::uno::Sequence < css::beans::NamedValue > aSeq { { u"Name"_ustr, css::uno::Any(rType) } };
669
0
    return GetFilterForProps( aSeq, nMust, nDont );
670
0
}
671
672
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4Extension( const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
673
0
{
674
0
    if ( m_rImpl.pList )
675
0
    {
676
0
        if (OUString sExt = ToUpper_Impl(rExt); !sExt.isEmpty())
677
0
        {
678
0
            if (sExt[0] != '.')
679
0
                sExt = "." + sExt;
680
681
0
            for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
682
0
            {
683
0
                SfxFilterFlags nFlags = pFilter->GetFilterFlags();
684
0
                if ((nFlags & nMust) == nMust && !(nFlags & nDont))
685
0
                {
686
0
                    OUString sWildCard = ToUpper_Impl(pFilter->GetWildcard().getGlob());
687
688
0
                    WildCard aCheck(sWildCard, ';');
689
0
                    if (aCheck.Matches(sExt))
690
0
                        return pFilter;
691
0
                }
692
0
            }
693
0
        }
694
695
0
        return nullptr;
696
0
    }
697
698
    // Use extension without dot!
699
0
    OUString sExt( rExt );
700
0
    if ( sExt.startsWith(".") )
701
0
        sExt = sExt.copy(1);
702
703
0
    css::uno::Sequence < css::beans::NamedValue > aSeq
704
0
        { { u"Extensions"_ustr, css::uno::Any(uno::Sequence < OUString > { sExt } ) } };
705
0
    return GetFilterForProps( aSeq, nMust, nDont );
706
0
}
707
708
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4ClipBoardId( SotClipboardFormatId nId, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
709
0
{
710
0
    if (nId == SotClipboardFormatId::NONE)
711
0
        return nullptr;
712
713
0
    css::uno::Sequence < css::beans::NamedValue > aSeq
714
0
        { { u"ClipboardFormat"_ustr, css::uno::Any(SotExchange::GetFormatName( nId )) } };
715
0
    return GetFilterForProps( aSeq, nMust, nDont );
716
0
}
717
718
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4UIName( std::u16string_view rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
719
0
{
720
0
    m_rImpl.InitForIterating();
721
0
    std::shared_ptr<const SfxFilter> pFirstFilter;
722
0
    for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
723
0
    {
724
0
        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
725
0
        if ( (nFlags & nMust) == nMust &&
726
0
             !(nFlags & nDont ) && pFilter->GetUIName() == rName )
727
0
        {
728
0
            if ( pFilter->GetFilterFlags() & SfxFilterFlags::PREFERED )
729
0
                return pFilter;
730
0
            else if ( !pFirstFilter )
731
0
                pFirstFilter = pFilter;
732
0
        }
733
0
    }
734
0
    return pFirstFilter;
735
0
}
736
737
std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4FilterName( const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
738
0
{
739
0
    std::u16string_view aName( rName );
740
0
    sal_Int32 nIndex = rName.indexOf(": ");
741
0
    if (  nIndex != -1 )
742
0
    {
743
0
        SAL_WARN( "sfx.bastyp", "Old filter name used!");
744
0
        aName = rName.subView( nIndex + 2 );
745
0
    }
746
747
0
    if ( bFirstRead )
748
0
    {
749
0
        uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
750
0
        uno::Reference< container::XNameAccess >     xFilterCFG                                                ;
751
0
        uno::Reference< container::XNameAccess >     xTypeCFG                                                  ;
752
0
        if( xServiceManager.is() )
753
0
        {
754
0
            static constexpr OUStringLiteral sFilterFactory = u"com.sun.star.document.FilterFactory";
755
0
            static constexpr OUStringLiteral sTypeDetection = u"com.sun.star.document.TypeDetection";
756
0
            xFilterCFG.set( xServiceManager->createInstance(  sFilterFactory ), uno::UNO_QUERY );
757
0
            xTypeCFG.set( xServiceManager->createInstance(  sTypeDetection ), uno::UNO_QUERY );
758
0
        }
759
760
0
        if( xFilterCFG.is() && xTypeCFG.is() )
761
0
        {
762
0
            if ( !pFilterArr )
763
0
                CreateFilterArr();
764
0
            else
765
0
            {
766
0
                for (const std::shared_ptr<const SfxFilter>& pFilter : *pFilterArr)
767
0
                {
768
0
                    SfxFilterFlags nFlags = pFilter->GetFilterFlags();
769
0
                    if ((nFlags & nMust) == nMust && !(nFlags & nDont) && pFilter->GetFilterName().equalsIgnoreAsciiCase(aName))
770
0
                        return pFilter;
771
0
                }
772
0
            }
773
774
0
            SfxFilterContainer::ReadSingleFilter_Impl( rName, xTypeCFG, xFilterCFG, false );
775
0
        }
776
0
    }
777
778
0
    SfxFilterList_Impl* pList = m_rImpl.pList;
779
0
    if ( !pList )
780
0
        pList = pFilterArr;
781
782
0
    for (const std::shared_ptr<const SfxFilter>& pFilter : *pList)
783
0
    {
784
0
        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
785
0
        if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().equalsIgnoreAsciiCase(aName))
786
0
            return pFilter;
787
0
    }
788
789
0
    return nullptr;
790
0
}
791
792
IMPL_LINK( SfxFilterMatcher, MaybeFileHdl_Impl, OUString*, pString, bool )
793
0
{
794
0
    std::shared_ptr<const SfxFilter> pFilter = GetFilter4Extension( *pString );
795
0
    return pFilter &&
796
0
        !pFilter->GetWildcard().Matches(u"") &&
797
0
        !pFilter->GetWildcard().Matches(u"*.*") &&
798
0
        !pFilter->GetWildcard().Matches(u"*");
799
0
}
800
801
802
SfxFilterMatcherIter::SfxFilterMatcherIter(
803
    const SfxFilterMatcher& rMatcher,
804
    SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP )
805
0
    : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ),
806
0
      nCurrent(0), m_rMatch(rMatcher.m_rImpl)
807
0
{
808
0
    if( nOrMask == static_cast<SfxFilterFlags>(0xffff) ) //Due to faulty build on s
809
0
        nOrMask = SfxFilterFlags::NONE;
810
0
    m_rMatch.InitForIterating();
811
0
}
812
813
814
std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::Find_Impl()
815
0
{
816
0
    std::shared_ptr<const SfxFilter> pFilter;
817
0
    while( nCurrent < m_rMatch.pList->size() )
818
0
    {
819
0
        pFilter = (*m_rMatch.pList)[nCurrent++];
820
0
        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
821
0
        if( ((nFlags & nOrMask) == nOrMask ) && !(nFlags & nAndMask ) )
822
0
            break;
823
0
        pFilter = nullptr;
824
0
    }
825
826
0
    return pFilter;
827
0
}
828
829
std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::First()
830
0
{
831
0
    nCurrent = 0;
832
0
    return Find_Impl();
833
0
}
834
835
836
std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::Next()
837
0
{
838
0
    return Find_Impl();
839
0
}
840
841
/*---------------------------------------------------------------
842
    helper to build own formatted string from given stringlist by
843
    using given separator
844
  ---------------------------------------------------------------*/
845
static OUString implc_convertStringlistToString( const uno::Sequence< OUString >& lList     ,
846
                                                 sal_Unicode                                        cSeparator,
847
                                                 std::u16string_view                                sPrefix   )
848
0
{
849
0
    OUStringBuffer   sString ( 1000 )           ;
850
0
    sal_Int32               nCount  = lList.getLength();
851
0
    sal_Int32               nItem   = 0                ;
852
0
    for( nItem=0; nItem<nCount; ++nItem )
853
0
    {
854
0
        if( !sPrefix.empty() )
855
0
        {
856
0
            sString.append( sPrefix );
857
0
        }
858
0
        sString.append( lList[nItem] );
859
0
        if( nItem+1<nCount )
860
0
        {
861
0
            sString.append( cSeparator );
862
0
        }
863
0
    }
864
0
    return sString.makeStringAndClear();
865
0
}
866
867
868
void SfxFilterContainer::ReadSingleFilter_Impl(
869
    const OUString& rName,
870
    const uno::Reference< container::XNameAccess >& xTypeCFG,
871
    const uno::Reference< container::XNameAccess >& xFilterCFG,
872
    bool bUpdate
873
    )
874
0
{
875
0
    OUString sFilterName( rName );
876
0
    SfxFilterList_Impl& rList = *pFilterArr;
877
0
    uno::Sequence< beans::PropertyValue > lFilterProperties;
878
0
    uno::Any aResult;
879
0
    try
880
0
    {
881
0
        aResult = xFilterCFG->getByName( sFilterName );
882
0
    }
883
0
    catch( container::NoSuchElementException& )
884
0
    {
885
0
        aResult = uno::Any();
886
0
    }
887
888
0
    if( !(aResult >>= lFilterProperties) )
889
0
        return;
890
891
    // collect information to add filter to container
892
    // (attention: some information aren't available on filter directly ... you must search for corresponding type too!)
893
0
    SfxFilterFlags       nFlags          = SfxFilterFlags::NONE;
894
0
    SotClipboardFormatId nClipboardId    = SotClipboardFormatId::NONE;
895
0
    sal_Int32       nFormatVersion  = 0 ;
896
0
    OUString sMimeType           ;
897
0
    OUString sType               ;
898
0
    OUString sUIName             ;
899
0
    OUString sHumanName          ;
900
0
    OUString sDefaultTemplate    ;
901
0
    OUString sUserData           ;
902
0
    OUString sExtension          ;
903
0
    OUString sServiceName        ;
904
0
    bool bEnabled = true         ;
905
906
    // first get directly available properties
907
0
    for (const auto& rFilterProperty : lFilterProperties)
908
0
    {
909
0
        if ( rFilterProperty.Name == "FileFormatVersion" )
910
0
        {
911
0
            rFilterProperty.Value >>= nFormatVersion;
912
0
        }
913
0
        else if ( rFilterProperty.Name == "TemplateName" )
914
0
        {
915
0
            rFilterProperty.Value >>= sDefaultTemplate;
916
0
        }
917
0
        else if ( rFilterProperty.Name == "Flags" )
918
0
        {
919
0
            sal_Int32 nTmp(0);
920
0
            rFilterProperty.Value >>= nTmp;
921
0
            assert((nTmp & ~o3tl::typed_flags<SfxFilterFlags>::mask) == 0);
922
0
            nFlags = static_cast<SfxFilterFlags>(nTmp);
923
0
        }
924
0
        else if ( rFilterProperty.Name == "UIName" )
925
0
        {
926
0
            rFilterProperty.Value >>= sUIName;
927
0
        }
928
0
        else if ( rFilterProperty.Name == "UserData" )
929
0
        {
930
0
            uno::Sequence< OUString > lUserData;
931
0
            rFilterProperty.Value >>= lUserData;
932
0
            sUserData = implc_convertStringlistToString( lUserData, ',', u"" );
933
0
        }
934
0
        else if ( rFilterProperty.Name == "DocumentService" )
935
0
        {
936
0
            rFilterProperty.Value >>= sServiceName;
937
0
        }
938
0
        else if (rFilterProperty.Name == "ExportExtension")
939
0
        {
940
            // Extension preferred by the filter.  This takes precedence
941
            // over those that are given in the file format type.
942
0
            rFilterProperty.Value >>= sExtension;
943
0
            sExtension = "*." + sExtension;
944
0
        }
945
0
        else if ( rFilterProperty.Name == "Type" )
946
0
        {
947
0
            rFilterProperty.Value >>= sType;
948
            // Try to get filter .. but look for any exceptions!
949
            // May be filter was deleted by another thread ...
950
0
            try
951
0
            {
952
0
                aResult = xTypeCFG->getByName( sType );
953
0
            }
954
0
            catch (const container::NoSuchElementException&)
955
0
            {
956
0
                aResult = uno::Any();
957
0
            }
958
959
0
            uno::Sequence< beans::PropertyValue > lTypeProperties;
960
0
            if( aResult >>= lTypeProperties )
961
0
            {
962
                // get indirect available properties then (types)
963
0
                for (const auto& rTypeProperty : lTypeProperties)
964
0
                {
965
0
                    if ( rTypeProperty.Name == "ClipboardFormat" )
966
0
                    {
967
0
                        rTypeProperty.Value >>= sHumanName;
968
0
                    }
969
0
                    else if ( rTypeProperty.Name == "MediaType" )
970
0
                    {
971
0
                        rTypeProperty.Value >>= sMimeType;
972
0
                    }
973
0
                    else if ( rTypeProperty.Name == "Extensions" )
974
0
                    {
975
0
                        if (sExtension.isEmpty())
976
0
                        {
977
0
                            uno::Sequence< OUString > lExtensions;
978
0
                            rTypeProperty.Value >>= lExtensions;
979
0
                            sExtension = implc_convertStringlistToString( lExtensions, ';', u"*." );
980
0
                        }
981
0
                    }
982
0
                }
983
0
            }
984
0
        }
985
0
        else if ( rFilterProperty.Name == "Enabled" )
986
0
        {
987
0
            rFilterProperty.Value >>= bEnabled;
988
0
        }
989
990
0
    }
991
992
0
    if ( sServiceName.isEmpty() )
993
0
        return;
994
995
    // old formats are found ... using HumanPresentableName!
996
0
    if( !sHumanName.isEmpty() )
997
0
    {
998
0
        nClipboardId = SotExchange::RegisterFormatName( sHumanName );
999
1000
        // For external filters ignore clipboard IDs
1001
0
        if(nFlags & SfxFilterFlags::STARONEFILTER)
1002
0
        {
1003
0
            nClipboardId = SotClipboardFormatId::NONE;
1004
0
        }
1005
0
    }
1006
    // register SfxFilter
1007
    // first erase module name from old filter names!
1008
    // e.g: "scalc: DIF" => "DIF"
1009
0
    sal_Int32 nStartRealName = sFilterName.indexOf( ": " );
1010
0
    if( nStartRealName != -1 )
1011
0
    {
1012
0
        SAL_WARN( "sfx.bastyp", "Old format, not supported!");
1013
0
        sFilterName = sFilterName.copy( nStartRealName+2 );
1014
0
    }
1015
1016
0
    std::shared_ptr<const SfxFilter> pFilter = bUpdate ? SfxFilter::GetFilterByName( sFilterName ) : nullptr;
1017
0
    if (!pFilter)
1018
0
    {
1019
0
        pFilter = std::make_shared<SfxFilter>( sFilterName             ,
1020
0
                                 sExtension              ,
1021
0
                                 nFlags                  ,
1022
0
                                 nClipboardId            ,
1023
0
                                 sType                   ,
1024
0
                                 sMimeType               ,
1025
0
                                 sUserData               ,
1026
0
                                 sServiceName            ,
1027
0
                                 bEnabled );
1028
0
        rList.push_back( pFilter );
1029
0
    }
1030
0
    else
1031
0
    {
1032
0
        SfxFilter* pFilt = const_cast<SfxFilter*>(pFilter.get());
1033
0
        pFilt->maFilterName  = sFilterName;
1034
0
        pFilt->aWildCard    = WildCard(sExtension, ';');
1035
0
        pFilt->nFormatType  = nFlags;
1036
0
        pFilt->lFormat      = nClipboardId;
1037
0
        pFilt->aTypeName    = sType;
1038
0
        pFilt->aMimeType    = sMimeType;
1039
0
        pFilt->aUserData    = sUserData;
1040
0
        pFilt->aServiceName = sServiceName;
1041
0
        pFilt->mbEnabled    = bEnabled;
1042
0
    }
1043
1044
0
    SfxFilter* pFilt = const_cast<SfxFilter*>(pFilter.get());
1045
1046
    // Don't forget to set right UIName!
1047
    // Otherwise internal name is used as fallback ...
1048
0
    pFilt->SetUIName( sUIName );
1049
0
    pFilt->SetDefaultTemplate( sDefaultTemplate );
1050
0
    if( nFormatVersion )
1051
0
    {
1052
0
        pFilt->SetVersion( nFormatVersion );
1053
0
    }
1054
0
}
1055
1056
void SfxFilterContainer::ReadFilters_Impl( bool bUpdate )
1057
0
{
1058
0
    if ( !pFilterArr )
1059
0
    {
1060
0
        CreateFilterArr();
1061
0
        assert(pFilterArr);
1062
0
    }
1063
1064
0
    bFirstRead = false;
1065
0
    SfxFilterList_Impl& rList = *pFilterArr;
1066
1067
0
    try
1068
0
    {
1069
        // get the FilterFactory service to access the registered filters ... and types!
1070
0
        uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
1071
0
        uno::Reference< container::XNameAccess >     xFilterCFG                                                ;
1072
0
        uno::Reference< container::XNameAccess >     xTypeCFG                                                  ;
1073
0
        if( xServiceManager.is() )
1074
0
        {
1075
0
            xFilterCFG.set( xServiceManager->createInstance(  u"com.sun.star.document.FilterFactory"_ustr ), uno::UNO_QUERY );
1076
0
            xTypeCFG.set( xServiceManager->createInstance(  u"com.sun.star.document.TypeDetection"_ustr ), uno::UNO_QUERY );
1077
0
        }
1078
1079
0
        if( xFilterCFG.is() && xTypeCFG.is() )
1080
0
        {
1081
            // select right query to get right set of filters for search module
1082
0
            const uno::Sequence< OUString > lFilterNames = xFilterCFG->getElementNames();
1083
0
            if ( lFilterNames.hasElements() )
1084
0
            {
1085
                // If list of filters already exist ...
1086
                // ReadExternalFilters must work in update mode.
1087
                // Best way seems to mark all filters NOT_INSTALLED
1088
                // and change it back for all valid filters afterwards.
1089
0
                if( !rList.empty() )
1090
0
                {
1091
0
                    bUpdate = true;
1092
0
                    for (const std::shared_ptr<const SfxFilter>& pFilter : rList)
1093
0
                    {
1094
0
                        SfxFilter* pNonConstFilter = const_cast<SfxFilter*>(pFilter.get());
1095
0
                        pNonConstFilter->nFormatType |= SFX_FILTER_NOTINSTALLED;
1096
0
                    }
1097
0
                }
1098
1099
                // get all properties of filters ... put it into the filter container
1100
0
                for( const OUString& sFilterName : lFilterNames )
1101
0
                {
1102
                    // Try to get filter .. but look for any exceptions!
1103
                    // May be filter was deleted by another thread ...
1104
0
                    ReadSingleFilter_Impl( sFilterName, xTypeCFG, xFilterCFG, bUpdate );
1105
0
                }
1106
0
            }
1107
0
        }
1108
0
    }
1109
0
    catch(const uno::Exception&)
1110
0
    {
1111
0
        SAL_WARN( "sfx.bastyp", "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached." );
1112
0
    }
1113
1114
0
    if ( bUpdate )
1115
0
    {
1116
        // global filter array was modified, factory specific ones might need an
1117
        // update too
1118
0
        for (const auto& aImpl : aImplArr)
1119
0
            aImpl->Update();
1120
0
    }
1121
0
}
1122
1123
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */