xref: /AOO41X/main/unotools/source/config/inetoptions.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_unotools.hxx"
26 #include <unotools/inetoptions.hxx>
27 #include "rtl/instance.hxx"
28 #include <tools/urlobj.hxx>
29 #ifndef _WILDCARD_HXX
30 #include <tools/wldcrd.hxx>
31 #endif
32 
33 #include <algorithm>
34 #include <map>
35 #include <set>
36 #include <vector>
37 #include <utility>
38 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
39 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/system/XProxySettings.hpp>
42 #include <com/sun/star/uno/Any.hxx>
43 #include <com/sun/star/uno/Exception.hpp>
44 #include <com/sun/star/uno/Reference.hxx>
45 #include <com/sun/star/uno/RuntimeException.hpp>
46 #include <osl/mutex.hxx>
47 #include <rtl/ustring.h>
48 #include <rtl/ustring.hxx>
49 #include <sal/types.h>
50 #include <unotools/configitem.hxx>
51 #include <unotools/processfactory.hxx>
52 #include <osl/diagnose.h>
53 #include <salhelper/refobj.hxx>
54 #include <rtl/logfile.hxx>
55 #include "itemholder1.hxx"
56 
57 using namespace com::sun;
58 
59 //============================================================================
60 //
61 //  takeAny
62 //
63 //============================================================================
64 
65 namespace {
66 
67 template< typename T > inline T takeAny(star::uno::Any const & rAny)
68 {
69     T aValue = T();
70     rAny >>= aValue;
71     return aValue;
72 }
73 
74 }
75 
76 //============================================================================
77 //
78 //  SvtInetOptions::Impl
79 //
80 //============================================================================
81 
82 class SvtInetOptions::Impl: public salhelper::ReferenceObject,
83                             public utl::ConfigItem
84 {
85 public:
86     enum Index
87     {
88         INDEX_NO_PROXY,
89         INDEX_PROXY_TYPE,
90         INDEX_FTP_PROXY_NAME,
91         INDEX_FTP_PROXY_PORT,
92         INDEX_HTTP_PROXY_NAME,
93         INDEX_HTTP_PROXY_PORT
94     };
95 
96     Impl();
97 
98     star::uno::Any getProperty(Index nIndex);
99 
100     void
101     setProperty(Index nIndex, star::uno::Any const & rValue, bool bFlush);
102 
103     inline void flush() { Commit(); }
104 
105     void
106     addPropertiesChangeListener(
107         star::uno::Sequence< rtl::OUString > const & rPropertyNames,
108         star::uno::Reference< star::beans::XPropertiesChangeListener > const &
109             rListener);
110 
111     void
112     removePropertiesChangeListener(
113         star::uno::Sequence< rtl::OUString > const & rPropertyNames,
114         star::uno::Reference< star::beans::XPropertiesChangeListener > const &
115             rListener);
116 
117 private:
118     enum { ENTRY_COUNT = INDEX_HTTP_PROXY_PORT + 1 };
119 
120     struct Entry
121     {
122         enum State { UNKNOWN, KNOWN, MODIFIED };
123 
124         inline Entry(): m_eState(UNKNOWN) {}
125 
126         rtl::OUString m_aName;
127         star::uno::Any m_aValue;
128         State m_eState;
129     };
130 
131     // MSVC has problems with the below Map type when
132     // star::uno::Reference< star::beans::XPropertiesChangeListener > is not
133     // wrapped in class Listener:
134     class Listener:
135         public star::uno::Reference< star::beans::XPropertiesChangeListener >
136     {
137     public:
138         Listener(star::uno::Reference<
139                          star::beans::XPropertiesChangeListener > const &
140                      rListener):
141             star::uno::Reference< star::beans::XPropertiesChangeListener >(
142                 rListener)
143         {}
144     };
145 
146     typedef std::map< Listener, std::set< rtl::OUString > > Map;
147 
148     osl::Mutex m_aMutex;
149     Entry m_aEntries[ENTRY_COUNT];
150     Map m_aListeners;
151 
152     virtual inline ~Impl() { Commit(); }
153 
154     virtual void Notify(star::uno::Sequence< rtl::OUString > const & rKeys);
155 
156     virtual void Commit();
157 
158     void notifyListeners(star::uno::Sequence< rtl::OUString > const & rKeys);
159 };
160 
161 //============================================================================
162 // virtual
163 void
164 SvtInetOptions::Impl::Notify(star::uno::Sequence< rtl::OUString > const &
165                                  rKeys)
166 {
167     {
168         osl::MutexGuard aGuard(m_aMutex);
169         for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
170             for (sal_Int32 j = 0; j < ENTRY_COUNT; ++j)
171                 if (rKeys[i] == m_aEntries[j].m_aName)
172                 {
173                     m_aEntries[j].m_eState = Entry::UNKNOWN;
174                     break;
175                 }
176     }
177     notifyListeners(rKeys);
178 }
179 
180 //============================================================================
181 // virtual
182 void SvtInetOptions::Impl::Commit()
183 {
184     star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
185     star::uno::Sequence< star::uno::Any > aValues(ENTRY_COUNT);
186     sal_Int32 nCount = 0;
187     {
188         osl::MutexGuard aGuard(m_aMutex);
189         for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
190             if (m_aEntries[i].m_eState == Entry::MODIFIED)
191             {
192                 aKeys[nCount] = m_aEntries[i].m_aName;
193                 aValues[nCount] = m_aEntries[i].m_aValue;
194                 ++nCount;
195                 m_aEntries[i].m_eState = Entry::KNOWN;
196             }
197     }
198     if (nCount > 0)
199     {
200         aKeys.realloc(nCount);
201         aValues.realloc(nCount);
202         PutProperties(aKeys, aValues);
203     }
204 }
205 
206 //============================================================================
207 void
208 SvtInetOptions::Impl::notifyListeners(
209     star::uno::Sequence< rtl::OUString > const & rKeys)
210 {
211     typedef
212         std::vector< std::pair< star::uno::Reference<
213                                     star::beans::XPropertiesChangeListener >,
214                                 star::uno::Sequence<
215                                     star::beans::PropertyChangeEvent > > >
216     List;
217     List aNotifications;
218     {
219         osl::MutexGuard aGuard(m_aMutex);
220         aNotifications.reserve(m_aListeners.size());
221         Map::const_iterator aMapEnd(m_aListeners.end());
222         for (Map::const_iterator aIt(m_aListeners.begin()); aIt != aMapEnd;
223              ++aIt)
224         {
225             const Map::mapped_type &rSet = aIt->second;
226             Map::mapped_type::const_iterator aSetEnd(rSet.end());
227             star::uno::Sequence< star::beans::PropertyChangeEvent >
228                 aEvents(rKeys.getLength());
229             sal_Int32 nCount = 0;
230             for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
231             {
232                 rtl::OUString
233                     aTheKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
234                                               "Inet/")));
235                 aTheKey += rKeys[i];
236                 if (rSet.find(aTheKey) != aSetEnd)
237                 {
238                     aEvents[nCount].PropertyName = aTheKey;
239                     aEvents[nCount].PropertyHandle = -1;
240                     ++nCount;
241                 }
242             }
243             if (nCount > 0)
244             {
245                 aEvents.realloc(nCount);
246                 aNotifications.
247                     push_back(std::make_pair< List::value_type::first_type,
248                                               List::value_type::second_type >(
249                                   aIt->first, aEvents));
250             }
251         }
252     }
253     for (List::size_type i = 0; i < aNotifications.size(); ++i)
254         if (aNotifications[i].first.is())
255             aNotifications[i].first->
256                 propertiesChange(aNotifications[i].second);
257 }
258 
259 //============================================================================
260 SvtInetOptions::Impl::Impl():
261     ConfigItem(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Inet/Settings")))
262 {
263     m_aEntries[INDEX_NO_PROXY].m_aName
264         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetNoProxy"));
265     m_aEntries[INDEX_PROXY_TYPE].m_aName
266         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetProxyType"));
267     m_aEntries[INDEX_FTP_PROXY_NAME].m_aName
268         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyName"));
269     m_aEntries[INDEX_FTP_PROXY_PORT].m_aName
270         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyPort"));
271     m_aEntries[INDEX_HTTP_PROXY_NAME].m_aName
272         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyName"));
273     m_aEntries[INDEX_HTTP_PROXY_PORT].m_aName
274         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyPort"));
275 
276     star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
277     for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
278         aKeys[i] = m_aEntries[i].m_aName;
279     if (!EnableNotification(aKeys))
280         OSL_ENSURE(false,
281                    "SvtInetOptions::Impl::Impl(): Bad EnableNotifications()");
282 }
283 
284 //============================================================================
285 star::uno::Any SvtInetOptions::Impl::getProperty(Index nPropIndex)
286 {
287     for (int nTryCount = 0; nTryCount < 10; ++nTryCount)
288     {
289         {
290             osl::MutexGuard aGuard(m_aMutex);
291             if (m_aEntries[nPropIndex].m_eState != Entry::UNKNOWN)
292                 return m_aEntries[nPropIndex].m_aValue;
293         }
294         star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
295         int nIndices[ENTRY_COUNT];
296         sal_Int32 nCount = 0;
297         {
298             osl::MutexGuard aGuard(m_aMutex);
299             for (int i = 0; i < ENTRY_COUNT; ++i)
300                 if (m_aEntries[i].m_eState == Entry::UNKNOWN)
301                 {
302                     aKeys[nCount] = m_aEntries[i].m_aName;
303                     nIndices[nCount] = i;
304                     ++nCount;
305                 }
306         }
307         if (nCount > 0)
308         {
309             aKeys.realloc(nCount);
310             star::uno::Sequence< star::uno::Any >
311                 aValues(GetProperties(aKeys));
312             OSL_ENSURE(aValues.getLength() == nCount,
313                        "SvtInetOptions::Impl::getProperty():"
314                            " Bad GetProperties() result");
315             nCount = std::min(nCount, aValues.getLength());
316             {
317                 osl::MutexGuard aGuard(m_aMutex);
318                 for (sal_Int32 i = 0; i < nCount; ++i)
319                 {
320                     int nIndex = nIndices[i];
321                     if (m_aEntries[nIndex].m_eState == Entry::UNKNOWN)
322                     {
323                         m_aEntries[nIndices[i]].m_aValue = aValues[i];
324                         m_aEntries[nIndices[i]].m_eState = Entry::KNOWN;
325                     }
326                 }
327             }
328         }
329     }
330     OSL_ENSURE(false,
331                "SvtInetOptions::Impl::getProperty(): Possible life lock");
332     {
333         osl::MutexGuard aGuard(m_aMutex);
334         return m_aEntries[nPropIndex].m_aValue;
335     }
336 }
337 
338 //============================================================================
339 void SvtInetOptions::Impl::setProperty(Index nIndex,
340                                        star::uno::Any const & rValue,
341                                        bool bFlush)
342 {
343     SetModified();
344     {
345         osl::MutexGuard aGuard(m_aMutex);
346         m_aEntries[nIndex].m_aValue = rValue;
347         m_aEntries[nIndex].m_eState = bFlush ? Entry::KNOWN : Entry::MODIFIED;
348     }
349 
350     star::uno::Sequence< rtl::OUString > aKeys(1);
351     aKeys[0] = m_aEntries[nIndex].m_aName;
352     if (bFlush)
353     {
354         star::uno::Sequence< star::uno::Any > aValues(1);
355         aValues[0] = rValue;
356         PutProperties(aKeys, aValues);
357     }
358     else
359         notifyListeners(aKeys);
360 }
361 
362 //============================================================================
363 void
364 SvtInetOptions::Impl::addPropertiesChangeListener(
365     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
366     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
367         rListener)
368 {
369     osl::MutexGuard aGuard(m_aMutex);
370     Map::mapped_type & rEntry = m_aListeners[rListener];
371     for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
372         rEntry.insert(rPropertyNames[i]);
373 }
374 
375 //============================================================================
376 void
377 SvtInetOptions::Impl::removePropertiesChangeListener(
378     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
379     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
380         rListener)
381 {
382     osl::MutexGuard aGuard(m_aMutex);
383     Map::iterator aIt(m_aListeners.find(rListener));
384     if (aIt != m_aListeners.end())
385     {
386         for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
387             aIt->second.erase(rPropertyNames[i]);
388         if (aIt->second.empty())
389             m_aListeners.erase(aIt);
390     }
391 }
392 
393 //============================================================================
394 //
395 //  SvtInetOptions
396 //
397 //============================================================================
398 
399 namespace
400 {
401     class LocalSingleton : public rtl::Static< osl::Mutex, LocalSingleton >
402     {
403     };
404 }
405 
406 // static
407 SvtInetOptions::Impl * SvtInetOptions::m_pImpl = 0;
408 
409 //============================================================================
410 SvtInetOptions::SvtInetOptions()
411 {
412     osl::MutexGuard aGuard(LocalSingleton::get());
413     if (!m_pImpl)
414     {
415         RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtInetOptions_Impl::ctor()");
416         m_pImpl = new Impl;
417 
418         ItemHolder1::holdConfigItem(E_INETOPTIONS);
419     }
420     m_pImpl->acquire();
421 }
422 
423 //============================================================================
424 SvtInetOptions::~SvtInetOptions()
425 {
426     osl::MutexGuard aGuard(LocalSingleton::get());
427     if (m_pImpl->release() == 0)
428         m_pImpl = 0;
429 }
430 
431 //============================================================================
432 rtl::OUString SvtInetOptions::GetProxyNoProxy() const
433 {
434     return takeAny< rtl::OUString >(m_pImpl->
435                                         getProperty(Impl::INDEX_NO_PROXY));
436 }
437 
438 //============================================================================
439 sal_Int32 SvtInetOptions::GetProxyType() const
440 {
441     return takeAny< sal_Int32 >(m_pImpl->
442                                     getProperty(Impl::INDEX_PROXY_TYPE));
443 }
444 
445 //============================================================================
446 rtl::OUString SvtInetOptions::GetProxyFtpName() const
447 {
448     return takeAny< rtl::OUString >(m_pImpl->
449                                         getProperty(
450                                             Impl::INDEX_FTP_PROXY_NAME));
451 }
452 
453 //============================================================================
454 sal_Int32 SvtInetOptions::GetProxyFtpPort() const
455 {
456     return takeAny< sal_Int32 >(m_pImpl->
457                                     getProperty(Impl::INDEX_FTP_PROXY_PORT));
458 }
459 
460 //============================================================================
461 rtl::OUString SvtInetOptions::GetProxyHttpName() const
462 {
463     return takeAny< rtl::OUString >(m_pImpl->
464                                         getProperty(
465                                             Impl::INDEX_HTTP_PROXY_NAME));
466 }
467 
468 //============================================================================
469 sal_Int32 SvtInetOptions::GetProxyHttpPort() const
470 {
471     return takeAny< sal_Int32 >(m_pImpl->
472                                     getProperty(Impl::INDEX_HTTP_PROXY_PORT));
473 }
474 
475 //============================================================================
476 void SvtInetOptions::SetProxyNoProxy(rtl::OUString const & rValue,
477                                      bool bFlush)
478 {
479     m_pImpl->setProperty(Impl::INDEX_NO_PROXY,
480                          star::uno::makeAny(rValue),
481                          bFlush);
482 }
483 
484 //============================================================================
485 void SvtInetOptions::SetProxyType(ProxyType eValue, bool bFlush)
486 {
487     m_pImpl->setProperty(Impl::INDEX_PROXY_TYPE,
488                          star::uno::makeAny(sal_Int32(eValue)),
489                          bFlush);
490 }
491 
492 //============================================================================
493 void SvtInetOptions::SetProxyFtpName(rtl::OUString const & rValue,
494                                      bool bFlush)
495 {
496     m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_NAME,
497                          star::uno::makeAny(rValue),
498                          bFlush);
499 }
500 
501 //============================================================================
502 void SvtInetOptions::SetProxyFtpPort(sal_Int32 nValue, bool bFlush)
503 {
504     m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_PORT,
505                          star::uno::makeAny(nValue),
506                          bFlush);
507 }
508 
509 //============================================================================
510 void SvtInetOptions::SetProxyHttpName(rtl::OUString const & rValue,
511                                       bool bFlush)
512 {
513     m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_NAME,
514                          star::uno::makeAny(rValue),
515                          bFlush);
516 }
517 
518 //============================================================================
519 void SvtInetOptions::SetProxyHttpPort(sal_Int32 nValue, bool bFlush)
520 {
521     m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_PORT,
522                          star::uno::makeAny(nValue),
523                          bFlush);
524 }
525 
526 //============================================================================
527 void SvtInetOptions::flush()
528 {
529     m_pImpl->flush();
530 }
531 
532 //============================================================================
533 void
534 SvtInetOptions::addPropertiesChangeListener(
535     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
536     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
537         rListener)
538 {
539     m_pImpl->addPropertiesChangeListener(rPropertyNames, rListener);
540 }
541 
542 //============================================================================
543 void
544 SvtInetOptions::removePropertiesChangeListener(
545     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
546     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
547         rListener)
548 {
549     m_pImpl->removePropertiesChangeListener(rPropertyNames, rListener);
550 }
551