Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/unotools/source/config/useroptions.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 <sal/config.h>
21
22
#include <unotools/useroptions.hxx>
23
#include <unotools/syslocale.hxx>
24
#include <com/sun/star/uno/Any.hxx>
25
#include "itemholder1.hxx"
26
27
#include <cppuhelper/implbase.hxx>
28
#include <com/sun/star/beans/Property.hpp>
29
#include <com/sun/star/beans/XPropertySet.hpp>
30
#include <com/sun/star/beans/PropertyAttribute.hpp>
31
#include <com/sun/star/container/XNameAccess.hpp>
32
#include <com/sun/star/util/XChangesListener.hpp>
33
#include <com/sun/star/util/XChangesNotifier.hpp>
34
#include <com/sun/star/util/ChangesEvent.hpp>
35
#include <comphelper/configurationhelper.hxx>
36
#include <comphelper/processfactory.hxx>
37
#include <i18nlangtag/mslangid.hxx>
38
#include <i18nlangtag/languagetag.hxx>
39
#include <o3tl/enumarray.hxx>
40
#include <o3tl/string_view.hxx>
41
#include <comphelper/diagnose_ex.hxx>
42
43
using namespace utl;
44
using namespace com::sun::star;
45
46
// vOptionNames[] -- names of the user option entries
47
// The order must correspond to the enum class UserOptToken in useroptions.hxx.
48
constexpr o3tl::enumarray<UserOptToken, OUString> vOptionNames = {
49
    u"l"_ustr,                         // UserOptToken::City
50
    u"o"_ustr,                         // UserOptToken::Company
51
    u"c"_ustr,                         // UserOptToken::Country
52
    u"mail"_ustr,                      // UserOptToken::Email
53
    u"facsimiletelephonenumber"_ustr,  // UserOptToken::Fax
54
    u"givenname"_ustr,                 // UserOptToken::FirstName
55
    u"sn"_ustr,                        // UserOptToken::LastName
56
    u"position"_ustr,                  // UserOptToken::Position
57
    u"st"_ustr,                        // UserOptToken::State
58
    u"street"_ustr,                    // UserOptToken::Street
59
    u"homephone"_ustr,                 // UserOptToken::TelephoneHome
60
    u"telephonenumber"_ustr,           // UserOptToken::TelephoneWork
61
    u"title"_ustr,                     // UserOptToken::Title
62
    u"initials"_ustr,                  // UserOptToken::ID
63
    u"postalcode"_ustr,                // UserOptToken::Zip
64
    u"fathersname"_ustr,               // UserOptToken::FathersName
65
    u"apartment"_ustr,                 // UserOptToken::Apartment
66
    u"signingkey"_ustr,                // UserOptToken::SigningKey
67
    u"encryptionkey"_ustr,             // UserOptToken::EncryptionKey
68
    u"encrypttoself"_ustr,             // UserOptToken::EncryptToSelf
69
    u"signingkeydisplayname"_ustr,     // UserOptToken::SigningKeyDisplayName
70
    u"encryptionkeydisplayname"_ustr,  // UserOptToken::EncryptionKeyDisplayName
71
};
72
73
std::weak_ptr<SvtUserOptions::Impl> SvtUserOptions::xSharedImpl;
74
75
class SvtUserOptions::ChangeListener : public cppu::WeakImplHelper<util::XChangesListener>
76
{
77
public:
78
6
    explicit ChangeListener (Impl& rParent): m_rParent(rParent) { }
79
80
    // XChangesListener
81
    virtual void SAL_CALL changesOccurred (util::ChangesEvent const& Event) override;
82
    // XEventListener
83
    virtual void SAL_CALL disposing (lang::EventObject const& Source) override;
84
85
private:
86
    Impl& m_rParent;
87
};
88
89
class SvtUserOptions::Impl : public utl::ConfigurationBroadcaster
90
{
91
public:
92
    Impl ();
93
94
    OUString GetFullName () const;
95
96
    bool IsTokenReadonly (UserOptToken nToken) const;
97
    OUString GetToken (UserOptToken nToken) const;
98
    void     SetToken (UserOptToken nToken, OUString const& rNewToken);
99
    bool     GetBoolValue (UserOptToken nToken) const;
100
    void     SetBoolValue (UserOptToken nToken, bool bNewValue);
101
    void     Notify ();
102
103
private:
104
    uno::Reference<util::XChangesListener> m_xChangeListener;
105
    uno::Reference<container::XNameAccess> m_xCfg;
106
    uno::Reference<beans::XPropertySet>    m_xData;
107
108
    template < typename ValueType >
109
    ValueType GetValue_Impl( UserOptToken nToken ) const;
110
    template < typename ValueType >
111
    void SetValue_Impl( UserOptToken nToken, ValueType const& rNewValue );
112
};
113
114
void SvtUserOptions::ChangeListener::changesOccurred (util::ChangesEvent const& rEvent)
115
0
{
116
0
    if (rEvent.Changes.hasElements())
117
0
        m_rParent.Notify();
118
0
}
119
120
void SvtUserOptions::ChangeListener::disposing (lang::EventObject const& rSource)
121
0
{
122
0
    try
123
0
    {
124
0
        uno::Reference<util::XChangesNotifier> xChgNot(rSource.Source, uno::UNO_QUERY);
125
0
        if (xChgNot)
126
0
            xChgNot->removeChangesListener(this);
127
0
    }
128
0
    catch (uno::Exception&)
129
0
    {
130
0
    }
131
0
}
132
133
SvtUserOptions::Impl::Impl() :
134
6
    m_xChangeListener( new ChangeListener(*this) )
135
6
{
136
6
    try
137
6
    {
138
6
        m_xCfg.set(
139
6
            comphelper::ConfigurationHelper::openConfig(
140
6
                comphelper::getProcessComponentContext(),
141
6
                u"org.openoffice.UserProfile/Data"_ustr,
142
6
                comphelper::EConfigurationModes::Standard
143
6
            ),
144
6
            uno::UNO_QUERY
145
6
        );
146
147
6
        m_xData.set(m_xCfg, uno::UNO_QUERY);
148
6
        uno::Reference<util::XChangesNotifier> xChgNot(m_xCfg, uno::UNO_QUERY);
149
6
        try
150
6
        {
151
6
            xChgNot->addChangesListener(m_xChangeListener);
152
6
        }
153
6
        catch (uno::RuntimeException&)
154
6
        {
155
0
        }
156
6
    }
157
6
    catch (uno::Exception const&)
158
6
    {
159
6
        DBG_UNHANDLED_EXCEPTION("unotools.config");
160
6
        m_xCfg.clear();
161
6
    }
162
6
}
163
164
template < typename ValueType >
165
ValueType SvtUserOptions::Impl::GetValue_Impl (UserOptToken nToken) const
166
34.3k
{
167
34.3k
    ValueType sToken = ValueType();
168
34.3k
    try
169
34.3k
    {
170
34.3k
        if (m_xData.is())
171
0
            m_xData->getPropertyValue(vOptionNames[nToken]) >>= sToken;
172
34.3k
    }
173
34.3k
    catch (uno::Exception const&)
174
34.3k
    {
175
0
        DBG_UNHANDLED_EXCEPTION("unotools.config");
176
0
    }
177
34.3k
    return sToken;
178
34.3k
}
rtl::OUString SvtUserOptions::Impl::GetValue_Impl<rtl::OUString>(UserOptToken) const
Line
Count
Source
166
34.3k
{
167
34.3k
    ValueType sToken = ValueType();
168
34.3k
    try
169
34.3k
    {
170
34.3k
        if (m_xData.is())
171
0
            m_xData->getPropertyValue(vOptionNames[nToken]) >>= sToken;
172
34.3k
    }
173
34.3k
    catch (uno::Exception const&)
174
34.3k
    {
175
0
        DBG_UNHANDLED_EXCEPTION("unotools.config");
176
0
    }
177
34.3k
    return sToken;
178
34.3k
}
Unexecuted instantiation: bool SvtUserOptions::Impl::GetValue_Impl<bool>(UserOptToken) const
179
180
template < typename ValueType >
181
void SvtUserOptions::Impl::SetValue_Impl (UserOptToken nToken, ValueType const& sToken)
182
0
{
183
0
    try
184
0
    {
185
0
        if (m_xData.is())
186
0
             m_xData->setPropertyValue(vOptionNames[nToken], uno::Any(sToken));
187
0
        comphelper::ConfigurationHelper::flush(m_xCfg);
188
0
    }
189
0
    catch (uno::Exception const&)
190
0
    {
191
0
        DBG_UNHANDLED_EXCEPTION("unotools.config");
192
0
    }
193
0
}
Unexecuted instantiation: void SvtUserOptions::Impl::SetValue_Impl<rtl::OUString>(UserOptToken, rtl::OUString const&)
Unexecuted instantiation: void SvtUserOptions::Impl::SetValue_Impl<bool>(UserOptToken, bool const&)
194
195
OUString SvtUserOptions::Impl::GetToken (UserOptToken nToken) const
196
34.3k
{
197
34.3k
    return GetValue_Impl<OUString>( nToken );
198
34.3k
}
199
200
void SvtUserOptions::Impl::SetToken (UserOptToken nToken, OUString const& sToken)
201
0
{
202
0
    SetValue_Impl<OUString>( nToken, sToken );
203
0
}
204
205
bool SvtUserOptions::Impl::GetBoolValue (UserOptToken nToken) const
206
0
{
207
0
    return GetValue_Impl<bool>( nToken );
208
0
}
209
210
void SvtUserOptions::Impl::SetBoolValue (UserOptToken nToken, bool bNewValue)
211
0
{
212
0
    SetValue_Impl<bool>( nToken, bNewValue );
213
0
}
214
215
OUString SvtUserOptions::Impl::GetFullName () const
216
12.5k
{
217
12.5k
    OUString sFullName;
218
12.5k
    LanguageType const eLang = SvtSysLocale().GetUILanguageTag().getLanguageType();
219
12.5k
    if (eLang == LANGUAGE_RUSSIAN)
220
0
    {
221
0
        sFullName = GetToken(UserOptToken::FirstName).trim();
222
0
        if (!sFullName.isEmpty())
223
0
            sFullName += " ";
224
0
        sFullName += o3tl::trim(GetToken(UserOptToken::FathersName));
225
0
        if (!sFullName.isEmpty())
226
0
            sFullName += " ";
227
0
        sFullName += o3tl::trim(GetToken(UserOptToken::LastName));
228
0
    }
229
12.5k
    else
230
12.5k
    {
231
12.5k
        if (MsLangId::isFamilyNameFirst(eLang))
232
0
        {
233
0
            sFullName = GetToken(UserOptToken::LastName).trim();
234
0
            if (!sFullName.isEmpty())
235
0
                sFullName += " ";
236
0
            sFullName += o3tl::trim(GetToken(UserOptToken::FirstName));
237
0
        }
238
12.5k
        else
239
12.5k
        {
240
12.5k
            sFullName = GetToken(UserOptToken::FirstName).trim();
241
12.5k
            if (!sFullName.isEmpty())
242
0
                sFullName += " ";
243
12.5k
            sFullName += o3tl::trim(GetToken(UserOptToken::LastName));
244
12.5k
        }
245
12.5k
    }
246
12.5k
    sFullName = sFullName.trim();
247
248
12.5k
    return sFullName;
249
12.5k
}
250
251
void SvtUserOptions::Impl::Notify ()
252
0
{
253
0
    NotifyListeners(ConfigurationHints::NONE);
254
0
}
255
256
bool SvtUserOptions::Impl::IsTokenReadonly (UserOptToken nToken) const
257
0
{
258
0
    uno::Reference<beans::XPropertySet> xData(m_xCfg, uno::UNO_QUERY);
259
0
    uno::Reference<beans::XPropertySetInfo> xInfo = xData->getPropertySetInfo();
260
0
    beans::Property aProp = xInfo->getPropertyByName(vOptionNames[nToken]);
261
0
    return ((aProp.Attributes & beans::PropertyAttribute::READONLY) ==
262
0
            beans::PropertyAttribute::READONLY);
263
0
}
264
265
static std::recursive_mutex& GetInitMutex()
266
37.7k
{
267
37.7k
    static std::recursive_mutex gMutex;
268
37.7k
    return gMutex;
269
37.7k
}
270
271
272
SvtUserOptions::SvtUserOptions ()
273
7.99k
{
274
    // Global access, must be guarded (multithreading)
275
7.99k
    std::unique_lock aGuard(GetInitMutex());
276
277
7.99k
    xImpl = xSharedImpl.lock();
278
7.99k
    if (!xImpl)
279
6
    {
280
6
        xImpl = std::make_shared<Impl>();
281
6
        xSharedImpl = xImpl;
282
6
        aGuard.unlock(); // because holdConfigItem will call this constructor
283
6
        ItemHolder1::holdConfigItem(EItem::UserOptions);
284
6
    }
285
7.99k
    xImpl->AddListener(this);
286
7.99k
}
287
288
SvtUserOptions::~SvtUserOptions()
289
7.98k
{
290
    // Global access, must be guarded (multithreading)
291
7.98k
    std::unique_lock aGuard( GetInitMutex() );
292
7.98k
    xImpl->RemoveListener(this);
293
7.98k
}
294
295
0
OUString SvtUserOptions::GetCompany        () const { return GetToken(UserOptToken::Company); }
296
609
OUString SvtUserOptions::GetFirstName      () const { return GetToken(UserOptToken::FirstName); }
297
609
OUString SvtUserOptions::GetLastName       () const { return GetToken(UserOptToken::LastName); }
298
589
OUString SvtUserOptions::GetID             () const { return GetToken(UserOptToken::ID); }
299
0
OUString SvtUserOptions::GetStreet         () const { return GetToken(UserOptToken::Street); }
300
0
OUString SvtUserOptions::GetCity           () const { return GetToken(UserOptToken::City); }
301
0
OUString SvtUserOptions::GetState          () const { return GetToken(UserOptToken::State); }
302
0
OUString SvtUserOptions::GetZip            () const { return GetToken(UserOptToken::Zip); }
303
0
OUString SvtUserOptions::GetCountry        () const { return GetToken(UserOptToken::Country); }
304
0
OUString SvtUserOptions::GetPosition       () const { return GetToken(UserOptToken::Position); }
305
0
OUString SvtUserOptions::GetTitle          () const { return GetToken(UserOptToken::Title); }
306
0
OUString SvtUserOptions::GetTelephoneHome  () const { return GetToken(UserOptToken::TelephoneHome); }
307
0
OUString SvtUserOptions::GetTelephoneWork  () const { return GetToken(UserOptToken::TelephoneWork); }
308
0
OUString SvtUserOptions::GetFax            () const { return GetToken(UserOptToken::Fax); }
309
0
OUString SvtUserOptions::GetEmail          () const { return GetToken(UserOptToken::Email); }
310
0
OUString SvtUserOptions::GetSigningKey     () const { return GetToken(UserOptToken::SigningKey); }
311
0
OUString SvtUserOptions::GetEncryptionKey  () const { return GetToken(UserOptToken::EncryptionKey); }
312
0
OUString SvtUserOptions::GetSigningKeyDisplayName () const { return GetToken(UserOptToken::SigningKeyDisplayName); }
313
0
OUString SvtUserOptions::GetEncryptionKeyDisplayName () const { return GetToken(UserOptToken::EncryptionKeyDisplayName); }
314
315
bool SvtUserOptions::IsTokenReadonly (UserOptToken nToken) const
316
0
{
317
0
    std::unique_lock aGuard(GetInitMutex());
318
0
    return xImpl->IsTokenReadonly(nToken);
319
0
}
320
321
OUString SvtUserOptions::GetToken (UserOptToken nToken) const
322
9.20k
{
323
9.20k
    std::unique_lock aGuard(GetInitMutex());
324
9.20k
    return xImpl->GetToken(nToken);
325
9.20k
}
326
327
void SvtUserOptions::SetToken (UserOptToken nToken, OUString const& rNewToken)
328
0
{
329
0
    std::unique_lock aGuard(GetInitMutex());
330
0
    xImpl->SetToken(nToken, rNewToken);
331
0
}
332
333
void SvtUserOptions::SetBoolValue (UserOptToken nToken, bool bNewValue)
334
0
{
335
0
    std::unique_lock aGuard(GetInitMutex());
336
0
    xImpl->SetBoolValue(nToken, bNewValue);
337
0
}
338
339
bool SvtUserOptions::GetEncryptToSelf() const
340
0
{
341
0
    std::unique_lock aGuard(GetInitMutex());
342
0
    return xImpl->GetBoolValue(UserOptToken::EncryptToSelf);
343
0
}
344
345
OUString SvtUserOptions::GetFullName () const
346
12.5k
{
347
12.5k
    std::unique_lock aGuard(GetInitMutex());
348
12.5k
    return xImpl->GetFullName();
349
12.5k
}
350
351
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */