Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/doc/docfac.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 <com/sun/star/container/XNameAccess.hpp>
21
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
22
#include <com/sun/star/document/XTypeDetection.hpp>
23
#include <com/sun/star/frame/ModuleManager.hpp>
24
#include <com/sun/star/frame/XLoadable.hpp>
25
#include <com/sun/star/frame/XStorable.hpp>
26
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
27
#include <comphelper/processfactory.hxx>
28
#include <comphelper/propertyvalue.hxx>
29
#include <unotools/moduleoptions.hxx>
30
#include <comphelper/sequenceashashmap.hxx>
31
#include <comphelper/configurationhelper.hxx>
32
33
#include <sfx2/docfilt.hxx>
34
#include <sfx2/docfac.hxx>
35
#include <sfx2/viewfac.hxx>
36
#include <sfx2/fcontnr.hxx>
37
#include <sfx2/module.hxx>
38
#include "syspath.hxx"
39
#include <osl/file.hxx>
40
#include <osl/security.hxx>
41
42
#include <sal/log.hxx>
43
#include <tools/debug.hxx>
44
#include <tools/globname.hxx>
45
46
#include <memory>
47
#include <utility>
48
49
using namespace ::com::sun::star;
50
51
52
struct SfxObjectFactory_Impl
53
{
54
    std::vector<SfxViewFactory*> aViewFactoryArr;// List of <SfxViewFactory>s
55
    OUString                     aServiceName;
56
    SfxFilterContainer*          pFilterContainer;
57
    SfxModule*                   pModule;
58
    SvGlobalName                 aClassName;
59
60
    SfxObjectFactory_Impl() :
61
46
        pFilterContainer    ( nullptr ),
62
46
        pModule             ( nullptr )
63
46
        {}
64
};
65
66
SfxFilterContainer* SfxObjectFactory::GetFilterContainer() const
67
0
{
68
0
    return pImpl->pFilterContainer;
69
0
}
70
71
SfxObjectFactory::SfxObjectFactory
72
(
73
    const SvGlobalName&     rName,
74
    OUString          sName
75
46
) :    m_sFactoryName(std::move( sName )),
76
46
       pImpl( new SfxObjectFactory_Impl )
77
46
{
78
46
    pImpl->pFilterContainer = new SfxFilterContainer( m_sFactoryName );
79
46
    pImpl->aClassName = rName;
80
46
}
81
82
SfxObjectFactory::~SfxObjectFactory()
83
46
{
84
46
    delete pImpl->pFilterContainer;
85
46
}
86
87
88
void SfxObjectFactory::RegisterViewFactory
89
(
90
    SfxViewFactory &rFactory
91
)
92
65
{
93
#if OSL_DEBUG_LEVEL > 0
94
    {
95
        const OUString sViewName( rFactory.GetAPIViewName() );
96
        for (auto const& viewFactory : pImpl->aViewFactoryArr)
97
        {
98
            if ( viewFactory->GetAPIViewName() != sViewName )
99
                continue;
100
            SAL_WARN( "sfx", "SfxObjectFactory::RegisterViewFactory: duplicate view name: " << sViewName );
101
            break;
102
        }
103
    }
104
#endif
105
65
    auto it = std::find_if(pImpl->aViewFactoryArr.begin(), pImpl->aViewFactoryArr.end(),
106
65
        [&rFactory](SfxViewFactory* pFactory) { return pFactory->GetOrdinal() > rFactory.GetOrdinal(); });
107
65
    pImpl->aViewFactoryArr.insert(it, &rFactory);
108
65
}
109
110
111
sal_uInt16 SfxObjectFactory::GetViewFactoryCount() const
112
12.8k
{
113
12.8k
    return pImpl->aViewFactoryArr.size();
114
12.8k
}
115
116
117
SfxViewFactory& SfxObjectFactory::GetViewFactory(sal_uInt16 i) const
118
17.0k
{
119
17.0k
    return *pImpl->aViewFactoryArr[i];
120
17.0k
}
121
122
123
SfxModule* SfxObjectFactory::GetModule() const
124
153k
{
125
153k
    return pImpl->pModule;
126
153k
}
127
128
void SfxObjectFactory::SetModule_Impl( SfxModule *pMod )
129
45
{
130
45
    pImpl->pModule = pMod;
131
45
}
132
133
void SfxObjectFactory::SetSystemTemplate( const OUString& rServiceName, const OUString& rTemplateName )
134
0
{
135
0
    static const int nMaxPathSize = 16000;
136
137
0
    const OUString sConfPath = "Office/Factories/" + rServiceName;
138
0
    static constexpr OUString PROP_DEF_TEMPL_CHANGED
139
0
        = u"ooSetupFactorySystemDefaultTemplateChanged"_ustr;
140
141
0
    static const char DEF_TPL_STR[] = "/soffice.";
142
143
0
    OUString sUserTemplateURL;
144
0
    OUString sPath;
145
0
    sal_Unicode aPathBuffer[nMaxPathSize];
146
0
    if ( SystemPath::GetUserTemplateLocation( aPathBuffer, nMaxPathSize ))
147
0
        sPath = OUString( aPathBuffer );
148
0
    osl::FileBase::getFileURLFromSystemPath( sPath, sUserTemplateURL );
149
150
0
    if ( sUserTemplateURL.isEmpty())
151
0
        return;
152
153
0
    try
154
0
    {
155
0
        uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
156
0
        uno::Reference< uno::XInterface > xConfig = ::comphelper::ConfigurationHelper::openConfig(
157
0
            ::comphelper::getProcessComponentContext(), u"/org.openoffice.Setup"_ustr, ::comphelper::EConfigurationModes::Standard );
158
159
0
        OUString aActualFilter;
160
0
        ::comphelper::ConfigurationHelper::readRelativeKey( xConfig, sConfPath, u"ooSetupFactoryActualFilter"_ustr ) >>= aActualFilter;
161
0
        bool bChanged(false);
162
0
        ::comphelper::ConfigurationHelper::readRelativeKey( xConfig, sConfPath, PROP_DEF_TEMPL_CHANGED ) >>= bChanged;
163
164
0
        uno::Reference< container::XNameAccess > xFilterFactory(
165
0
            xFactory->createInstance( u"com.sun.star.document.FilterFactory"_ustr ), uno::UNO_QUERY_THROW );
166
0
        uno::Reference< container::XNameAccess > xTypeDetection(
167
0
            xFactory->createInstance( u"com.sun.star.document.TypeDetection"_ustr ), uno::UNO_QUERY_THROW );
168
169
0
        OUString aActualFilterTypeName;
170
0
        uno::Sequence< beans::PropertyValue > aActuralFilterData;
171
0
        xFilterFactory->getByName( aActualFilter ) >>= aActuralFilterData;
172
0
        for (const auto& rProp : aActuralFilterData)
173
0
            if ( rProp.Name == "Type" )
174
0
                rProp.Value >>= aActualFilterTypeName;
175
0
        ::comphelper::SequenceAsHashMap aProps1( xTypeDetection->getByName( aActualFilterTypeName ) );
176
0
        uno::Sequence< OUString > aAllExt =
177
0
            aProps1.getUnpackedValueOrDefault(u"Extensions"_ustr, uno::Sequence< OUString >() );
178
        //To-do: check if aAllExt is empty first
179
0
        const OUString aExt = DEF_TPL_STR + aAllExt[0];
180
181
0
        sUserTemplateURL += aExt;
182
183
0
        uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
184
0
            ucb::SimpleFileAccess::create( ::comphelper::getComponentContext(xFactory) ) );
185
186
0
        OUString aBackupURL;
187
0
        ::osl::Security().getConfigDir(aBackupURL);
188
0
        aBackupURL += "/temp";
189
190
0
        if ( !xSimpleFileAccess->exists( aBackupURL ) )
191
0
            xSimpleFileAccess->createFolder( aBackupURL );
192
193
0
        aBackupURL += aExt;
194
195
0
        if ( !rTemplateName.isEmpty() )
196
0
        {
197
0
            if ( xSimpleFileAccess->exists( sUserTemplateURL ) && !bChanged )
198
0
                xSimpleFileAccess->copy( sUserTemplateURL, aBackupURL );
199
200
0
            uno::Reference< document::XTypeDetection > xTypeDetector( xTypeDetection, uno::UNO_QUERY );
201
0
            ::comphelper::SequenceAsHashMap aProps2( xTypeDetection->getByName( xTypeDetector->queryTypeByURL( rTemplateName ) ) );
202
0
            OUString aFilterName =
203
0
                aProps2.getUnpackedValueOrDefault(u"PreferredFilter"_ustr, OUString() );
204
205
0
            uno::Sequence< beans::PropertyValue > aArgs{
206
0
                comphelper::makePropertyValue(u"FilterName"_ustr, aFilterName),
207
0
                comphelper::makePropertyValue(u"AsTemplate"_ustr, true),
208
0
                comphelper::makePropertyValue(u"URL"_ustr, rTemplateName)
209
0
            };
210
211
0
            uno::Reference< frame::XLoadable > xLoadable( xFactory->createInstance( rServiceName ), uno::UNO_QUERY );
212
0
            xLoadable->load( aArgs );
213
214
0
            aArgs.realloc( 2 );
215
0
            auto pArgs = aArgs.getArray();
216
0
            pArgs[1].Name = "Overwrite";
217
0
            pArgs[1].Value <<= true;
218
219
0
            uno::Reference< frame::XStorable > xStorable( xLoadable, uno::UNO_QUERY );
220
0
            xStorable->storeToURL( sUserTemplateURL, aArgs );
221
0
            ::comphelper::ConfigurationHelper::writeRelativeKey( xConfig, sConfPath, PROP_DEF_TEMPL_CHANGED, uno::Any( true ));
222
0
            ::comphelper::ConfigurationHelper::flush( xConfig );
223
0
        }
224
0
        else
225
0
        {
226
0
            DBG_ASSERT( bChanged, "invalid ooSetupFactorySystemDefaultTemplateChanged value!" );
227
228
0
            xSimpleFileAccess->copy( aBackupURL, sUserTemplateURL );
229
0
            xSimpleFileAccess->kill( aBackupURL );
230
0
            ::comphelper::ConfigurationHelper::writeRelativeKey( xConfig, sConfPath, PROP_DEF_TEMPL_CHANGED, uno::Any( false ));
231
0
            ::comphelper::ConfigurationHelper::flush( xConfig );
232
0
        }
233
0
    }
234
0
    catch(const uno::Exception&)
235
0
    {
236
0
    }
237
0
}
238
239
void SfxObjectFactory::SetStandardTemplate( const OUString& rServiceName, const OUString& rTemplate )
240
0
{
241
0
    SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(rServiceName);
242
0
    if (eFac == SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
243
0
        eFac = SvtModuleOptions::ClassifyFactoryByShortName(rServiceName);
244
0
    if (eFac != SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
245
0
    {
246
0
        SetSystemTemplate( rServiceName, rTemplate );
247
0
        SvtModuleOptions().SetFactoryStandardTemplate(eFac, rTemplate);
248
0
    }
249
0
}
250
251
OUString SfxObjectFactory::GetStandardTemplate( std::u16string_view rServiceName )
252
0
{
253
0
    SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(rServiceName);
254
0
    if (eFac == SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
255
0
        eFac = SvtModuleOptions::ClassifyFactoryByShortName(rServiceName);
256
257
0
    if (eFac != SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
258
0
        return SvtModuleOptions().GetFactoryStandardTemplate(eFac);
259
260
0
    return OUString();
261
0
}
262
263
std::shared_ptr<const SfxFilter> SfxObjectFactory::GetTemplateFilter() const
264
0
{
265
0
    sal_uInt16 nVersion=0;
266
0
    SfxFilterMatcher aMatcher ( m_sFactoryName );
267
0
    SfxFilterMatcherIter aIter( aMatcher );
268
0
    std::shared_ptr<const SfxFilter> pFilter;
269
0
    std::shared_ptr<const SfxFilter> pTemp = aIter.First();
270
0
    while ( pTemp )
271
0
    {
272
0
        if( pTemp->IsOwnFormat() && pTemp->IsOwnTemplateFormat() && ( pTemp->GetVersion() > nVersion ) )
273
0
        {
274
0
            pFilter = pTemp;
275
0
            nVersion = static_cast<sal_uInt16>(pTemp->GetVersion());
276
0
        }
277
278
0
        pTemp = aIter.Next();
279
0
    }
280
281
0
    return pFilter;
282
0
}
283
284
void SfxObjectFactory::SetDocumentServiceName( const OUString& rServiceName )
285
39
{
286
39
    pImpl->aServiceName = rServiceName;
287
39
}
288
289
const OUString& SfxObjectFactory::GetDocumentServiceName() const
290
45.8M
{
291
45.8M
    return pImpl->aServiceName;
292
45.8M
}
293
294
const SvGlobalName& SfxObjectFactory::GetClassId() const
295
0
{
296
0
    return pImpl->aClassName;
297
0
}
298
299
OUString SfxObjectFactory::GetFactoryURL() const
300
0
{
301
0
    return "private:factory/" + m_sFactoryName;
302
0
}
303
304
OUString SfxObjectFactory::GetModuleName() const
305
0
{
306
0
    try
307
0
    {
308
0
        const css::uno::Reference< css::uno::XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
309
310
0
        css::uno::Reference< css::frame::XModuleManager2 > xModuleManager(
311
0
            css::frame::ModuleManager::create(xContext));
312
313
0
        ::comphelper::SequenceAsHashMap aPropSet( xModuleManager->getByName(GetDocumentServiceName()) );
314
0
        return aPropSet.getUnpackedValueOrDefault(u"ooSetupFactoryUIName"_ustr, OUString());
315
0
    }
316
0
    catch(const css::uno::RuntimeException&)
317
0
    {
318
0
        throw;
319
0
    }
320
0
    catch(const css::uno::Exception&)
321
0
    {
322
0
    }
323
324
0
    return OUString();
325
0
}
326
327
328
sal_uInt16 SfxObjectFactory::GetViewNo_Impl( const SfxInterfaceId i_nViewId, const sal_uInt16 i_nFallback ) const
329
4.26k
{
330
4.26k
    for ( sal_uInt16 curViewNo = 0; curViewNo < GetViewFactoryCount(); ++curViewNo )
331
4.26k
    {
332
4.26k
        const SfxInterfaceId curViewId = GetViewFactory( curViewNo ).GetOrdinal();
333
4.26k
        if ( i_nViewId == curViewId )
334
4.26k
           return curViewNo;
335
4.26k
    }
336
0
    return i_nFallback;
337
4.26k
}
338
339
SfxViewFactory* SfxObjectFactory::GetViewFactoryByViewName( std::u16string_view i_rViewName ) const
340
8.50k
{
341
8.50k
    for (   sal_uInt16 nViewNo = 0;
342
8.57k
            nViewNo < GetViewFactoryCount();
343
8.50k
            ++nViewNo
344
8.50k
        )
345
8.50k
    {
346
8.50k
        SfxViewFactory& rViewFac( GetViewFactory( nViewNo ) );
347
8.50k
        if  (   ( rViewFac.GetAPIViewName() == i_rViewName )
348
4.24k
            ||  ( rViewFac.GetLegacyViewName() == i_rViewName )
349
8.50k
            )
350
8.42k
            return &rViewFac;
351
8.50k
    }
352
75
    return nullptr;
353
8.50k
}
354
355
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */