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