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_ucbhelper.hxx" 30 31 /************************************************************************** 32 TODO 33 ************************************************************************** 34 35 *************************************************************************/ 36 37 #include <utility> 38 #include <vector> 39 #include <list> 40 #include <osl/mutex.hxx> 41 #include <rtl/ref.hxx> 42 #include <osl/socket.hxx> 43 #include <rtl/ustrbuf.hxx> 44 #include <com/sun/star/container/XNameAccess.hpp> 45 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 46 #include <com/sun/star/util/XChangesListener.hpp> 47 #include <com/sun/star/util/XChangesNotifier.hpp> 48 #include <cppuhelper/implbase1.hxx> 49 #include "ucbhelper/proxydecider.hxx" 50 51 using namespace com::sun::star; 52 using namespace ucbhelper; 53 54 #define CONFIG_ROOT_KEY "org.openoffice.Inet/Settings" 55 #define PROXY_TYPE_KEY "ooInetProxyType" 56 #define NO_PROXY_LIST_KEY "ooInetNoProxy" 57 #define HTTP_PROXY_NAME_KEY "ooInetHTTPProxyName" 58 #define HTTP_PROXY_PORT_KEY "ooInetHTTPProxyPort" 59 #define HTTPS_PROXY_NAME_KEY "ooInetHTTPSProxyName" 60 #define HTTPS_PROXY_PORT_KEY "ooInetHTTPSProxyPort" 61 #define FTP_PROXY_NAME_KEY "ooInetFTPProxyName" 62 #define FTP_PROXY_PORT_KEY "ooInetFTPProxyPort" 63 64 //========================================================================= 65 namespace ucbhelper 66 { 67 68 //========================================================================= 69 namespace proxydecider_impl 70 { 71 72 // A simple case ignoring wildcard matcher. 73 class WildCard 74 { 75 private: 76 rtl::OString m_aWildString; 77 78 public: 79 WildCard( const rtl::OUString& rWildCard ) 80 : m_aWildString( 81 rtl::OUStringToOString( 82 rWildCard, RTL_TEXTENCODING_UTF8 ).toAsciiLowerCase() ) {} 83 84 bool Matches( const rtl::OUString & rStr ) const; 85 }; 86 87 //========================================================================= 88 typedef std::pair< WildCard, WildCard > NoProxyListEntry; 89 90 //========================================================================= 91 92 class HostnameCache 93 { 94 typedef std::pair< rtl::OUString, rtl::OUString > HostListEntry; 95 96 std::list< HostListEntry > m_aHostList; 97 sal_uInt32 m_nCapacity; 98 99 public: 100 explicit HostnameCache( sal_uInt32 nCapacity ) 101 : m_nCapacity( nCapacity ) {} 102 103 bool get( const rtl::OUString & rKey, rtl::OUString & rValue ) const 104 { 105 std::list< HostListEntry >::const_iterator it 106 = m_aHostList.begin(); 107 const std::list< HostListEntry >::const_iterator end 108 = m_aHostList.end(); 109 110 while ( it != end ) 111 { 112 if ( (*it).first == rKey ) 113 { 114 rValue = (*it).second; 115 return true; 116 } 117 it++; 118 } 119 return false; 120 } 121 122 void put( const rtl::OUString & rKey, const rtl::OUString & rValue ) 123 { 124 if ( m_aHostList.size() == m_nCapacity ) 125 m_aHostList.resize( m_nCapacity / 2 ); 126 127 m_aHostList.push_front( HostListEntry( rKey, rValue ) ); 128 } 129 }; 130 131 //========================================================================= 132 class InternetProxyDecider_Impl : 133 public cppu::WeakImplHelper1< util::XChangesListener > 134 { 135 mutable osl::Mutex m_aMutex; 136 InternetProxyServer m_aHttpProxy; 137 InternetProxyServer m_aHttpsProxy; 138 InternetProxyServer m_aFtpProxy; 139 const InternetProxyServer m_aEmptyProxy; 140 sal_Int32 m_nProxyType; 141 uno::Reference< util::XChangesNotifier > m_xNotifier; 142 std::vector< NoProxyListEntry > m_aNoProxyList; 143 mutable HostnameCache m_aHostnames; 144 145 private: 146 bool shouldUseProxy( const rtl::OUString & rHost, 147 sal_Int32 nPort, 148 bool bUseFullyQualified ) const; 149 public: 150 InternetProxyDecider_Impl( 151 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr ); 152 virtual ~InternetProxyDecider_Impl(); 153 154 static rtl::Reference< InternetProxyDecider_Impl > createInstance( 155 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr ); 156 157 void dispose(); 158 159 const InternetProxyServer & getProxy( const rtl::OUString & rProtocol, 160 const rtl::OUString & rHost, 161 sal_Int32 nPort ) const; 162 163 // XChangesListener 164 virtual void SAL_CALL changesOccurred( const util::ChangesEvent& Event ) 165 throw( uno::RuntimeException ); 166 167 // XEventListener ( base of XChangesLisetenr ) 168 virtual void SAL_CALL disposing( const lang::EventObject& Source ) 169 throw( uno::RuntimeException ); 170 171 private: 172 void setNoProxyList( const rtl::OUString & rNoProxyList ); 173 }; 174 175 //========================================================================= 176 //========================================================================= 177 // 178 // WildCard Implementation. 179 // 180 //========================================================================= 181 //========================================================================= 182 183 bool WildCard::Matches( const rtl::OUString& rString ) const 184 { 185 rtl::OString aString 186 = rtl::OUStringToOString( 187 rString, RTL_TEXTENCODING_UTF8 ).toAsciiLowerCase(); 188 const char * pStr = aString.getStr(); 189 const char * pWild = m_aWildString.getStr(); 190 191 int pos = 0; 192 int flag = 0; 193 194 while ( *pWild || flag ) 195 { 196 switch ( *pWild ) 197 { 198 case '?': 199 if ( *pStr == '\0' ) 200 return 0; 201 break; 202 203 default: 204 if ( ( *pWild == '\\' ) && ( ( *( pWild + 1 ) == '?' ) 205 || ( *( pWild + 1 ) == '*') ) ) 206 pWild++; 207 if ( *pWild != *pStr ) 208 if ( !pos ) 209 return 0; 210 else 211 pWild += pos; 212 else 213 break; 214 215 // Note: fall-thru's are intended! 216 217 case '*': 218 while ( *pWild == '*' ) 219 pWild++; 220 if ( *pWild == '\0' ) 221 return 1; 222 flag = 1; 223 pos = 0; 224 if ( *pStr == '\0' ) 225 return ( *pWild == '\0' ); 226 while ( *pStr && *pStr != *pWild ) 227 { 228 if ( *pWild == '?' ) { 229 pWild++; 230 while ( *pWild == '*' ) 231 pWild++; 232 } 233 pStr++; 234 if ( *pStr == '\0' ) 235 return ( *pWild == '\0' ); 236 } 237 break; 238 } 239 if ( *pWild != '\0' ) 240 pWild++; 241 if ( *pStr != '\0' ) 242 pStr++; 243 else 244 flag = 0; 245 if ( flag ) 246 pos--; 247 } 248 return ( *pStr == '\0' ) && ( *pWild == '\0' ); 249 } 250 251 //========================================================================= 252 bool getConfigStringValue( 253 const uno::Reference< container::XNameAccess > & xNameAccess, 254 const char * key, 255 rtl::OUString & value ) 256 { 257 try 258 { 259 if ( !( xNameAccess->getByName( rtl::OUString::createFromAscii( key ) ) 260 >>= value ) ) 261 { 262 OSL_ENSURE( sal_False, 263 "InternetProxyDecider - " 264 "Error getting config item value!" ); 265 return false; 266 } 267 } 268 catch ( lang::WrappedTargetException const & ) 269 { 270 return false; 271 } 272 catch ( container::NoSuchElementException const & ) 273 { 274 return false; 275 } 276 return true; 277 } 278 279 //========================================================================= 280 bool getConfigInt32Value( 281 const uno::Reference< container::XNameAccess > & xNameAccess, 282 const char * key, 283 sal_Int32 & value ) 284 { 285 try 286 { 287 uno::Any aValue = xNameAccess->getByName( 288 rtl::OUString::createFromAscii( key ) ); 289 if ( aValue.hasValue() && !( aValue >>= value ) ) 290 { 291 OSL_ENSURE( sal_False, 292 "InternetProxyDecider - " 293 "Error getting config item value!" ); 294 return false; 295 } 296 } 297 catch ( lang::WrappedTargetException const & ) 298 { 299 return false; 300 } 301 catch ( container::NoSuchElementException const & ) 302 { 303 return false; 304 } 305 return true; 306 } 307 308 //========================================================================= 309 //========================================================================= 310 // 311 // InternetProxyDecider_Impl Implementation. 312 // 313 //========================================================================= 314 //========================================================================= 315 316 InternetProxyDecider_Impl::InternetProxyDecider_Impl( 317 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr ) 318 : m_nProxyType( 0 ), 319 m_aHostnames( 256 ) // cache size 320 { 321 try 322 { 323 ////////////////////////////////////////////////////////////// 324 // Read proxy configuration from config db. 325 ////////////////////////////////////////////////////////////// 326 327 uno::Reference< lang::XMultiServiceFactory > xConfigProv( 328 rxSMgr->createInstance( 329 rtl::OUString::createFromAscii( 330 "com.sun.star.configuration.ConfigurationProvider" ) ), 331 uno::UNO_QUERY ); 332 333 uno::Sequence< uno::Any > aArguments( 1 ); 334 aArguments[ 0 ] <<= rtl::OUString::createFromAscii( CONFIG_ROOT_KEY ); 335 336 uno::Reference< uno::XInterface > xInterface( 337 xConfigProv->createInstanceWithArguments( 338 rtl::OUString::createFromAscii( 339 "com.sun.star.configuration.ConfigurationAccess" ), 340 aArguments ) ); 341 342 OSL_ENSURE( xInterface.is(), 343 "InternetProxyDecider - No config access!" ); 344 345 if ( xInterface.is() ) 346 { 347 uno::Reference< container::XNameAccess > xNameAccess( 348 xInterface, uno::UNO_QUERY ); 349 OSL_ENSURE( xNameAccess.is(), 350 "InternetProxyDecider - No name access!" ); 351 352 if ( xNameAccess.is() ) 353 { 354 // *** Proxy type *** 355 getConfigInt32Value( 356 xNameAccess, PROXY_TYPE_KEY, m_nProxyType ); 357 358 // *** No proxy list *** 359 rtl::OUString aNoProxyList; 360 getConfigStringValue( 361 xNameAccess, NO_PROXY_LIST_KEY, aNoProxyList ); 362 setNoProxyList( aNoProxyList ); 363 364 // *** HTTP *** 365 getConfigStringValue( 366 xNameAccess, HTTP_PROXY_NAME_KEY, m_aHttpProxy.aName ); 367 368 m_aHttpProxy.nPort = -1; 369 getConfigInt32Value( 370 xNameAccess, HTTP_PROXY_PORT_KEY, m_aHttpProxy.nPort ); 371 if ( m_aHttpProxy.nPort == -1 ) 372 m_aHttpProxy.nPort = 80; // standard HTTP port. 373 374 // *** HTTPS *** 375 getConfigStringValue( 376 xNameAccess, HTTPS_PROXY_NAME_KEY, m_aHttpsProxy.aName ); 377 378 m_aHttpsProxy.nPort = -1; 379 getConfigInt32Value( 380 xNameAccess, HTTPS_PROXY_PORT_KEY, m_aHttpsProxy.nPort ); 381 if ( m_aHttpsProxy.nPort == -1 ) 382 m_aHttpsProxy.nPort = 443; // standard HTTPS port. 383 384 // *** FTP *** 385 getConfigStringValue( 386 xNameAccess, FTP_PROXY_NAME_KEY, m_aFtpProxy.aName ); 387 388 m_aFtpProxy.nPort = -1; 389 getConfigInt32Value( 390 xNameAccess, FTP_PROXY_PORT_KEY, m_aFtpProxy.nPort ); 391 } 392 393 // Register as listener for config changes. 394 395 m_xNotifier = uno::Reference< util::XChangesNotifier >( 396 xInterface, uno::UNO_QUERY ); 397 398 OSL_ENSURE( m_xNotifier.is(), 399 "InternetProxyDecider - No notifier!" ); 400 401 if ( m_xNotifier.is() ) 402 m_xNotifier->addChangesListener( this ); 403 } 404 } 405 catch ( uno::Exception const & ) 406 { 407 // createInstance, createInstanceWithArguments 408 OSL_ENSURE( sal_False, "InternetProxyDecider - Exception!" ); 409 } 410 } 411 412 //========================================================================= 413 // virtual 414 InternetProxyDecider_Impl::~InternetProxyDecider_Impl() 415 { 416 } 417 418 //========================================================================= 419 void InternetProxyDecider_Impl::dispose() 420 { 421 uno::Reference< util::XChangesNotifier > xNotifier; 422 423 if ( m_xNotifier.is() ) 424 { 425 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 426 427 if ( m_xNotifier.is() ) 428 { 429 xNotifier = m_xNotifier; 430 m_xNotifier.clear(); 431 } 432 } 433 434 // Do this unguarded! 435 if ( xNotifier.is() ) 436 xNotifier->removeChangesListener( this ); 437 } 438 439 //========================================================================= 440 bool InternetProxyDecider_Impl::shouldUseProxy( const rtl::OUString & rHost, 441 sal_Int32 nPort, 442 bool bUseFullyQualified ) const 443 { 444 rtl::OUStringBuffer aBuffer; 445 446 if ( ( rHost.indexOf( ':' ) != -1 ) && 447 ( rHost[ 0 ] != sal_Unicode( '[' ) ) ) 448 { 449 // host is given as numeric IPv6 address 450 aBuffer.appendAscii( "[" ); 451 aBuffer.append( rHost ); 452 aBuffer.appendAscii( "]" ); 453 } 454 else 455 { 456 // host is given either as numeric IPv4 address or non-numeric hostname 457 aBuffer.append( rHost ); 458 } 459 460 aBuffer.append( sal_Unicode( ':' ) ); 461 aBuffer.append( rtl::OUString::valueOf( nPort ) ); 462 const rtl::OUString aHostAndPort( aBuffer.makeStringAndClear() ); 463 464 std::vector< NoProxyListEntry >::const_iterator it 465 = m_aNoProxyList.begin(); 466 const std::vector< NoProxyListEntry >::const_iterator end 467 = m_aNoProxyList.end(); 468 469 while ( it != end ) 470 { 471 if ( bUseFullyQualified ) 472 { 473 if ( (*it).second.Matches( aHostAndPort ) ) 474 return false; 475 } 476 else 477 { 478 if ( (*it).first.Matches( aHostAndPort ) ) 479 return false; 480 } 481 it++; 482 } 483 484 return true; 485 } 486 487 //========================================================================= 488 const InternetProxyServer & InternetProxyDecider_Impl::getProxy( 489 const rtl::OUString & rProtocol, 490 const rtl::OUString & rHost, 491 sal_Int32 nPort ) const 492 { 493 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 494 495 if ( m_nProxyType == 0 ) 496 { 497 // Never use proxy. 498 return m_aEmptyProxy; 499 } 500 501 if ( rHost.getLength() && m_aNoProxyList.size() ) 502 { 503 ////////////////////////////////////////////////////////////////// 504 // First, try direct hostname match - #110515# 505 ////////////////////////////////////////////////////////////////// 506 507 if ( !shouldUseProxy( rHost, nPort, false ) ) 508 return m_aEmptyProxy; 509 510 ////////////////////////////////////////////////////////////////// 511 // Second, try match against full qualified hostname - #104401# 512 ////////////////////////////////////////////////////////////////// 513 514 rtl::OUString aHost; 515 516 if ( ( rHost[ 0 ] == sal_Unicode( '[' ) ) && 517 ( rHost.getLength() > 1 ) ) 518 { 519 // host is given as numeric IPv6 address. name resolution 520 // functions need hostname without square brackets. 521 aHost = rHost.copy( 1, rHost.getLength() - 2 ); 522 } 523 else 524 { 525 aHost = rHost; 526 } 527 528 rtl::OUString aFullyQualifiedHost; 529 if ( !m_aHostnames.get( aHost, aFullyQualifiedHost ) ) 530 { 531 // This might be quite expensive (DNS lookup). 532 const osl::SocketAddr aAddr( aHost, nPort ); 533 aFullyQualifiedHost = aAddr.getHostname().toAsciiLowerCase(); 534 m_aHostnames.put( aHost, aFullyQualifiedHost ); 535 } 536 537 // Error resolving name? -> fallback. 538 if ( !aFullyQualifiedHost.getLength() ) 539 aFullyQualifiedHost = aHost; 540 541 if ( aFullyQualifiedHost != aHost ) 542 { 543 if ( !shouldUseProxy( aFullyQualifiedHost, nPort, false ) ) 544 return m_aEmptyProxy; 545 } 546 547 ////////////////////////////////////////////////////////////////// 548 // Third, try match of fully qualified entries in no-proxy list 549 // against full qualified hostname 550 // 551 // Example: 552 // list: staroffice-doc -> full: xyz.germany.sun.com 553 // in: staroffice-doc.germany.sun.com -> full: xyz.germany.sun.com 554 // 555 ////////////////////////////////////////////////////////////////// 556 557 if ( !shouldUseProxy( aFullyQualifiedHost, nPort, true ) ) 558 return m_aEmptyProxy; 559 } 560 561 if ( rProtocol.toAsciiLowerCase() 562 .equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ftp" ) ) ) 563 { 564 if ( m_aFtpProxy.aName.getLength() > 0 && m_aFtpProxy.nPort >= 0 ) 565 return m_aFtpProxy; 566 } 567 else if ( rProtocol.toAsciiLowerCase() 568 .equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) ) ) 569 { 570 if ( m_aHttpsProxy.aName.getLength() ) 571 return m_aHttpsProxy; 572 } 573 else if ( m_aHttpProxy.aName.getLength() ) 574 { 575 // All other protocols use the HTTP proxy. 576 return m_aHttpProxy; 577 } 578 return m_aEmptyProxy; 579 } 580 581 //========================================================================= 582 // virtual 583 void SAL_CALL InternetProxyDecider_Impl::changesOccurred( 584 const util::ChangesEvent& Event ) 585 throw( uno::RuntimeException ) 586 { 587 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 588 589 sal_Int32 nCount = Event.Changes.getLength(); 590 if ( nCount ) 591 { 592 const util::ElementChange* pElementChanges 593 = Event.Changes.getConstArray(); 594 for ( sal_Int32 n = 0; n < nCount; ++n ) 595 { 596 const util::ElementChange& rElem = pElementChanges[ n ]; 597 rtl::OUString aKey; 598 if ( ( rElem.Accessor >>= aKey ) && aKey.getLength() ) 599 { 600 if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 601 PROXY_TYPE_KEY ) ) ) 602 { 603 if ( !( rElem.Element >>= m_nProxyType ) ) 604 { 605 OSL_ENSURE( sal_False, 606 "InternetProxyDecider - changesOccurred - " 607 "Error getting config item value!" ); 608 } 609 } 610 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 611 NO_PROXY_LIST_KEY ) ) ) 612 { 613 rtl::OUString aNoProxyList; 614 if ( !( rElem.Element >>= aNoProxyList ) ) 615 { 616 OSL_ENSURE( sal_False, 617 "InternetProxyDecider - changesOccurred - " 618 "Error getting config item value!" ); 619 } 620 621 setNoProxyList( aNoProxyList ); 622 } 623 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 624 HTTP_PROXY_NAME_KEY ) ) ) 625 { 626 if ( !( rElem.Element >>= m_aHttpProxy.aName ) ) 627 { 628 OSL_ENSURE( sal_False, 629 "InternetProxyDecider - changesOccurred - " 630 "Error getting config item value!" ); 631 } 632 } 633 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 634 HTTP_PROXY_PORT_KEY ) ) ) 635 { 636 if ( !( rElem.Element >>= m_aHttpProxy.nPort ) ) 637 { 638 OSL_ENSURE( sal_False, 639 "InternetProxyDecider - changesOccurred - " 640 "Error getting config item value!" ); 641 } 642 643 if ( m_aHttpProxy.nPort == -1 ) 644 m_aHttpProxy.nPort = 80; // standard HTTP port. 645 } 646 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 647 HTTPS_PROXY_NAME_KEY ) ) ) 648 { 649 if ( !( rElem.Element >>= m_aHttpsProxy.aName ) ) 650 { 651 OSL_ENSURE( sal_False, 652 "InternetProxyDecider - changesOccurred - " 653 "Error getting config item value!" ); 654 } 655 } 656 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 657 HTTPS_PROXY_PORT_KEY ) ) ) 658 { 659 if ( !( rElem.Element >>= m_aHttpsProxy.nPort ) ) 660 { 661 OSL_ENSURE( sal_False, 662 "InternetProxyDecider - changesOccurred - " 663 "Error getting config item value!" ); 664 } 665 666 if ( m_aHttpsProxy.nPort == -1 ) 667 m_aHttpsProxy.nPort = 443; // standard HTTPS port. 668 } 669 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 670 FTP_PROXY_NAME_KEY ) ) ) 671 { 672 if ( !( rElem.Element >>= m_aFtpProxy.aName ) ) 673 { 674 OSL_ENSURE( sal_False, 675 "InternetProxyDecider - changesOccurred - " 676 "Error getting config item value!" ); 677 } 678 } 679 else if ( aKey.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 680 FTP_PROXY_PORT_KEY ) ) ) 681 { 682 if ( !( rElem.Element >>= m_aFtpProxy.nPort ) ) 683 { 684 OSL_ENSURE( sal_False, 685 "InternetProxyDecider - changesOccurred - " 686 "Error getting config item value!" ); 687 } 688 } 689 } 690 } 691 } 692 } 693 694 //========================================================================= 695 // virtual 696 void SAL_CALL InternetProxyDecider_Impl::disposing(const lang::EventObject&) 697 throw( uno::RuntimeException ) 698 { 699 if ( m_xNotifier.is() ) 700 { 701 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 702 703 if ( m_xNotifier.is() ) 704 m_xNotifier.clear(); 705 } 706 } 707 708 //========================================================================= 709 void InternetProxyDecider_Impl::setNoProxyList( 710 const rtl::OUString & rNoProxyList ) 711 { 712 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 713 714 m_aNoProxyList.clear(); 715 716 if ( rNoProxyList.getLength() ) 717 { 718 // List of connection endpoints hostname[:port], 719 // separated by semicolon. Wilcards allowed. 720 721 sal_Int32 nPos = 0; 722 sal_Int32 nEnd = rNoProxyList.indexOf( ';' ); 723 sal_Int32 nLen = rNoProxyList.getLength(); 724 725 do 726 { 727 if ( nEnd == -1 ) 728 nEnd = nLen; 729 730 rtl::OUString aToken = rNoProxyList.copy( nPos, nEnd - nPos ); 731 732 if ( aToken.getLength() ) 733 { 734 rtl::OUString aServer; 735 rtl::OUString aPort; 736 737 // numerical IPv6 address? 738 bool bIPv6Address = false; 739 sal_Int32 nClosedBracketPos = aToken.indexOf( ']' ); 740 if ( nClosedBracketPos == -1 ) 741 nClosedBracketPos = 0; 742 else 743 bIPv6Address = true; 744 745 sal_Int32 nColonPos = aToken.indexOf( ':', nClosedBracketPos ); 746 if ( nColonPos == -1 ) 747 { 748 // No port given, server pattern equals current token 749 aPort = rtl::OUString::createFromAscii( "*" ); 750 if ( aToken.indexOf( '*' ) == -1 ) 751 { 752 // pattern describes exactly one server 753 aServer = aToken; 754 } 755 756 aToken += rtl::OUString::createFromAscii( ":*" ); 757 } 758 else 759 { 760 // Port given, extract server pattern 761 sal_Int32 nAsterixPos = aToken.indexOf( '*' ); 762 aPort = aToken.copy( nColonPos + 1 ); 763 if ( nAsterixPos < nColonPos ) 764 { 765 // pattern describes exactly one server 766 aServer = aToken.copy( 0, nColonPos ); 767 } 768 } 769 770 rtl::OUStringBuffer aFullyQualifiedHost; 771 if ( aServer.getLength() ) 772 { 773 // Remember fully qualified server name if current list 774 // entry specifies exactly one non-fully qualified server 775 // name. 776 777 // remove square brackets from host name in case it's 778 // a numerical IPv6 address. 779 if ( bIPv6Address ) 780 aServer = aServer.copy( 1, aServer.getLength() - 2 ); 781 782 // This might be quite expensive (DNS lookup). 783 const osl::SocketAddr aAddr( aServer, 0 ); 784 rtl::OUString aTmp = aAddr.getHostname().toAsciiLowerCase(); 785 if ( aTmp != aServer.toAsciiLowerCase() ) 786 { 787 if ( bIPv6Address ) 788 { 789 aFullyQualifiedHost.appendAscii( "[" ); 790 aFullyQualifiedHost.append( aTmp ); 791 aFullyQualifiedHost.appendAscii( "]" ); 792 } 793 else 794 { 795 aFullyQualifiedHost.append( aTmp ); 796 } 797 aFullyQualifiedHost.appendAscii( ":" ); 798 aFullyQualifiedHost.append( aPort ); 799 } 800 } 801 802 m_aNoProxyList.push_back( 803 NoProxyListEntry( WildCard( aToken ), 804 WildCard( 805 aFullyQualifiedHost 806 .makeStringAndClear() ) ) ); 807 } 808 809 if ( nEnd != nLen ) 810 { 811 nPos = nEnd + 1; 812 nEnd = rNoProxyList.indexOf( ';', nPos ); 813 } 814 } 815 while ( nEnd != nLen ); 816 } 817 } 818 819 } // namespace proxydecider_impl 820 821 //========================================================================= 822 //========================================================================= 823 // 824 // InternetProxyDecider Implementation. 825 // 826 //========================================================================= 827 //========================================================================= 828 829 InternetProxyDecider::InternetProxyDecider( 830 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr ) 831 : m_pImpl( new proxydecider_impl::InternetProxyDecider_Impl( rxSMgr ) ) 832 { 833 m_pImpl->acquire(); 834 } 835 836 //========================================================================= 837 InternetProxyDecider::~InternetProxyDecider() 838 { 839 // Break circular reference between config listener and notifier. 840 m_pImpl->dispose(); 841 842 // Let him go... 843 m_pImpl->release(); 844 } 845 846 //========================================================================= 847 bool InternetProxyDecider::shouldUseProxy( const rtl::OUString & rProtocol, 848 const rtl::OUString & rHost, 849 sal_Int32 nPort ) const 850 { 851 const InternetProxyServer & rData = m_pImpl->getProxy( rProtocol, 852 rHost, 853 nPort ); 854 return ( rData.aName.getLength() > 0 ); 855 } 856 857 //========================================================================= 858 const InternetProxyServer & InternetProxyDecider::getProxy( 859 const rtl::OUString & rProtocol, 860 const rtl::OUString & rHost, 861 sal_Int32 nPort ) const 862 { 863 return m_pImpl->getProxy( rProtocol, rHost, nPort ); 864 } 865 866 } // namespace ucbhelper 867