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 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 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 123 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: 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 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 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 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 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 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 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 //============================================================================ 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 //============================================================================ 414 SvtInetOptions::~SvtInetOptions() 415 { 416 osl::MutexGuard aGuard(LocalSingleton::get()); 417 if (m_pImpl->release() == 0) 418 m_pImpl = 0; 419 } 420 421 //============================================================================ 422 rtl::OUString SvtInetOptions::GetProxyNoProxy() const 423 { 424 return takeAny< rtl::OUString >(m_pImpl-> 425 getProperty(Impl::INDEX_NO_PROXY)); 426 } 427 428 //============================================================================ 429 sal_Int32 SvtInetOptions::GetProxyType() const 430 { 431 return takeAny< sal_Int32 >(m_pImpl-> 432 getProperty(Impl::INDEX_PROXY_TYPE)); 433 } 434 435 //============================================================================ 436 rtl::OUString SvtInetOptions::GetProxyFtpName() const 437 { 438 return takeAny< rtl::OUString >(m_pImpl-> 439 getProperty( 440 Impl::INDEX_FTP_PROXY_NAME)); 441 } 442 443 //============================================================================ 444 sal_Int32 SvtInetOptions::GetProxyFtpPort() const 445 { 446 return takeAny< sal_Int32 >(m_pImpl-> 447 getProperty(Impl::INDEX_FTP_PROXY_PORT)); 448 } 449 450 //============================================================================ 451 rtl::OUString SvtInetOptions::GetProxyHttpName() const 452 { 453 return takeAny< rtl::OUString >(m_pImpl-> 454 getProperty( 455 Impl::INDEX_HTTP_PROXY_NAME)); 456 } 457 458 //============================================================================ 459 sal_Int32 SvtInetOptions::GetProxyHttpPort() const 460 { 461 return takeAny< sal_Int32 >(m_pImpl-> 462 getProperty(Impl::INDEX_HTTP_PROXY_PORT)); 463 } 464 465 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 517 void SvtInetOptions::flush() 518 { 519 m_pImpl->flush(); 520 } 521 522 //============================================================================ 523 void 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 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