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