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