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