1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
24 #include <osl/diagnose.h>
25 #include <osl/mutex.hxx>
26 #include <rtl/ref.hxx>
27 #include <osl/socket.hxx>
28 #include <rtl/ustrbuf.hxx>
29 #include <com/sun/star/container/XNameAccess.hpp>
30 #include <com/sun/star/configuration/theDefaultProvider.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/util/XChangesListener.hpp>
33 #include <com/sun/star/util/XChangesNotifier.hpp>
34 #include <cppuhelper/implbase.hxx>
35 #include <ucbhelper/proxydecider.hxx>
38 #include <o3tl/char16_t2wchar_t.hxx>
39 #define WIN32_LEAN_AND_MEAN
44 using namespace com::sun::star
;
45 using namespace ucbhelper
;
47 #define CONFIG_ROOT_KEY "org.openoffice.Inet/Settings"
48 #define PROXY_TYPE_KEY "ooInetProxyType"
49 #define NO_PROXY_LIST_KEY "ooInetNoProxy"
50 #define HTTP_PROXY_NAME_KEY "ooInetHTTPProxyName"
51 #define HTTP_PROXY_PORT_KEY "ooInetHTTPProxyPort"
52 #define HTTPS_PROXY_NAME_KEY "ooInetHTTPSProxyName"
53 #define HTTPS_PROXY_PORT_KEY "ooInetHTTPSProxyPort"
54 #define FTP_PROXY_NAME_KEY "ooInetFTPProxyName"
55 #define FTP_PROXY_PORT_KEY "ooInetFTPProxyPort"
62 namespace proxydecider_impl
65 // A simple case ignoring wildcard matcher.
69 OString
const m_aWildString
;
72 explicit WildCard( const OUString
& rWildCard
)
75 rWildCard
, RTL_TEXTENCODING_UTF8
).toAsciiLowerCase() ) {}
77 bool Matches( const OUString
& rStr
) const;
81 typedef std::pair
< WildCard
, WildCard
> NoProxyListEntry
;
85 typedef std::pair
< OUString
, OUString
> HostListEntry
;
87 std::deque
< HostListEntry
> m_aHostList
;
90 bool get( const OUString
& rKey
, OUString
& rValue
) const
92 for (auto const& host
: m_aHostList
)
94 if ( host
.first
== rKey
)
103 void put( const OUString
& rKey
, const OUString
& rValue
)
105 static constexpr sal_uInt32 nCapacity
= 256;
107 if ( m_aHostList
.size() == nCapacity
)
108 m_aHostList
.resize( nCapacity
/ 2 );
110 m_aHostList
.push_front( HostListEntry( rKey
, rValue
) );
115 class InternetProxyDecider_Impl
:
116 public cppu::WeakImplHelper
< util::XChangesListener
>
118 // see officecfg/registry/schema/org/openoffice/Inet.xcs for the definition of these values
119 enum class ProxyType
{ NoProxy
, Automatic
, Manual
};
120 mutable osl::Mutex m_aMutex
;
121 InternetProxyServer m_aHttpProxy
;
122 InternetProxyServer m_aHttpsProxy
;
123 InternetProxyServer m_aFtpProxy
;
124 const InternetProxyServer m_aEmptyProxy
;
125 ProxyType m_nProxyType
;
126 uno::Reference
< util::XChangesNotifier
> m_xNotifier
;
127 std::vector
< NoProxyListEntry
> m_aNoProxyList
;
128 mutable HostnameCache m_aHostnames
;
131 bool shouldUseProxy( const OUString
& rHost
,
133 bool bUseFullyQualified
) const;
135 explicit InternetProxyDecider_Impl(
136 const uno::Reference
< uno::XComponentContext
>& rxContext
);
140 InternetProxyServer
getProxy(const OUString
& rProtocol
,
141 const OUString
& rHost
,
142 sal_Int32 nPort
) const;
145 virtual void SAL_CALL
changesOccurred( const util::ChangesEvent
& Event
) override
;
147 // XEventListener ( base of XChangesLisetenr )
148 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) override
;
151 void setNoProxyList( const OUString
& rNoProxyList
);
155 // WildCard Implementation.
158 bool WildCard::Matches( const OUString
& rString
) const
161 = OUStringToOString( rString
, RTL_TEXTENCODING_UTF8
).toAsciiLowerCase();
162 const char * pStr
= aString
.getStr();
163 const char * pWild
= m_aWildString
.getStr();
168 while ( *pWild
|| flag
)
178 if ( ( *pWild
== '\\' ) && ( ( *( pWild
+ 1 ) == '?' )
179 || ( *( pWild
+ 1 ) == '*') ) )
181 if ( *pWild
!= *pStr
)
192 while ( *pWild
== '*' )
194 if ( *pWild
== '\0' )
199 return ( *pWild
== '\0' );
200 while ( *pStr
&& *pStr
!= *pWild
)
202 if ( *pWild
== '?' ) {
204 while ( *pWild
== '*' )
209 return ( *pWild
== '\0' );
213 if ( *pWild
!= '\0' )
222 return ( *pStr
== '\0' ) && ( *pWild
== '\0' );
226 static bool getConfigStringValue(
227 const uno::Reference
< container::XNameAccess
> & xNameAccess
,
233 if ( !( xNameAccess
->getByName( OUString::createFromAscii( key
) )
236 OSL_FAIL( "InternetProxyDecider - "
237 "Error getting config item value!" );
241 catch ( lang::WrappedTargetException
const & )
245 catch ( container::NoSuchElementException
const & )
253 static bool getConfigInt32Value(
254 const uno::Reference
< container::XNameAccess
> & xNameAccess
,
260 uno::Any aValue
= xNameAccess
->getByName(
261 OUString::createFromAscii( key
) );
262 if ( aValue
.hasValue() && !( aValue
>>= value
) )
264 OSL_FAIL( "InternetProxyDecider - "
265 "Error getting config item value!" );
269 catch ( lang::WrappedTargetException
const & )
273 catch ( container::NoSuchElementException
const & )
281 // InternetProxyDecider_Impl Implementation.
284 InternetProxyDecider_Impl::InternetProxyDecider_Impl(
285 const uno::Reference
< uno::XComponentContext
>& rxContext
)
286 : m_nProxyType( ProxyType::NoProxy
),
292 // Read proxy configuration from config db.
295 uno::Reference
< lang::XMultiServiceFactory
> xConfigProv
=
296 configuration::theDefaultProvider::get( rxContext
);
298 uno::Sequence
< uno::Any
> aArguments( 1 );
299 aArguments
[ 0 ] <<= OUString( CONFIG_ROOT_KEY
);
301 uno::Reference
< uno::XInterface
> xInterface(
302 xConfigProv
->createInstanceWithArguments(
303 "com.sun.star.configuration.ConfigurationAccess",
306 OSL_ENSURE( xInterface
.is(),
307 "InternetProxyDecider - No config access!" );
309 if ( xInterface
.is() )
311 uno::Reference
< container::XNameAccess
> xNameAccess(
312 xInterface
, uno::UNO_QUERY
);
313 OSL_ENSURE( xNameAccess
.is(),
314 "InternetProxyDecider - No name access!" );
316 if ( xNameAccess
.is() )
318 // *** Proxy type ***
321 xNameAccess
, PROXY_TYPE_KEY
, tmp
);
322 m_nProxyType
= static_cast<ProxyType
>(tmp
);
324 // *** No proxy list ***
325 OUString aNoProxyList
;
326 getConfigStringValue(
327 xNameAccess
, NO_PROXY_LIST_KEY
, aNoProxyList
);
328 setNoProxyList( aNoProxyList
);
331 getConfigStringValue(
332 xNameAccess
, HTTP_PROXY_NAME_KEY
, m_aHttpProxy
.aName
);
334 m_aHttpProxy
.nPort
= -1;
336 xNameAccess
, HTTP_PROXY_PORT_KEY
, m_aHttpProxy
.nPort
);
337 if ( m_aHttpProxy
.nPort
== -1 )
338 m_aHttpProxy
.nPort
= 80; // standard HTTP port.
341 getConfigStringValue(
342 xNameAccess
, HTTPS_PROXY_NAME_KEY
, m_aHttpsProxy
.aName
);
344 m_aHttpsProxy
.nPort
= -1;
346 xNameAccess
, HTTPS_PROXY_PORT_KEY
, m_aHttpsProxy
.nPort
);
347 if ( m_aHttpsProxy
.nPort
== -1 )
348 m_aHttpsProxy
.nPort
= 443; // standard HTTPS port.
351 getConfigStringValue(
352 xNameAccess
, FTP_PROXY_NAME_KEY
, m_aFtpProxy
.aName
);
354 m_aFtpProxy
.nPort
= -1;
356 xNameAccess
, FTP_PROXY_PORT_KEY
, m_aFtpProxy
.nPort
);
359 // Register as listener for config changes.
361 m_xNotifier
.set( xInterface
, uno::UNO_QUERY
);
363 OSL_ENSURE( m_xNotifier
.is(),
364 "InternetProxyDecider - No notifier!" );
366 if ( m_xNotifier
.is() )
367 m_xNotifier
->addChangesListener( this );
370 catch ( uno::Exception
const & )
372 // createInstance, createInstanceWithArguments
373 OSL_FAIL( "InternetProxyDecider - Exception!" );
377 void InternetProxyDecider_Impl::dispose()
379 uno::Reference
< util::XChangesNotifier
> xNotifier
;
381 if ( m_xNotifier
.is() )
383 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
385 if ( m_xNotifier
.is() )
387 xNotifier
= m_xNotifier
;
392 // Do this unguarded!
393 if ( xNotifier
.is() )
394 xNotifier
->removeChangesListener( this );
398 bool InternetProxyDecider_Impl::shouldUseProxy( const OUString
& rHost
,
400 bool bUseFullyQualified
) const
402 OUStringBuffer aBuffer
;
404 if ( ( rHost
.indexOf( ':' ) != -1 ) &&
405 ( rHost
[ 0 ] != '[' ) )
407 // host is given as numeric IPv6 address
408 aBuffer
.append( "[" );
409 aBuffer
.append( rHost
);
410 aBuffer
.append( "]" );
414 // host is given either as numeric IPv4 address or non-numeric hostname
415 aBuffer
.append( rHost
);
418 aBuffer
.append( ':' );
419 aBuffer
.append( OUString::number( nPort
) );
420 const OUString
aHostAndPort( aBuffer
.makeStringAndClear() );
422 for (auto const& noProxy
: m_aNoProxyList
)
424 if ( bUseFullyQualified
)
426 if ( noProxy
.second
.Matches( aHostAndPort
) )
431 if ( noProxy
.first
.Matches( aHostAndPort
) )
442 struct GetPACProxyData
444 const OUString
& m_rProtocol
;
445 const OUString
& m_rHost
;
447 bool m_bAutoDetect
= false;
448 OUString m_sAutoConfigUrl
;
449 InternetProxyServer m_ProxyServer
;
451 GetPACProxyData(const OUString
& rProtocol
, const OUString
& rHost
, sal_Int32 nPort
)
452 : m_rProtocol(rProtocol
)
459 // Tries to get proxy configuration using WinHttpGetProxyForUrl, which supports Web Proxy Auto-Discovery
460 // (WPAD) protocol and manually configured address to get Proxy Auto-Configuration (PAC) file.
461 // The WinINet/WinHTTP functions cannot correctly run in a STA COM thread, so use a dedicated thread
462 DWORD WINAPI
GetPACProxyThread(_In_ LPVOID lpParameter
)
465 GetPACProxyData
* pData
= static_cast<GetPACProxyData
*>(lpParameter
);
467 OUString
url(pData
->m_rProtocol
+ "://" + pData
->m_rHost
+ ":"
468 + OUString::number(pData
->m_nPort
));
470 HINTERNET hInternet
= WinHttpOpen(L
"Mozilla 5.0", WINHTTP_ACCESS_TYPE_NO_PROXY
,
471 WINHTTP_NO_PROXY_NAME
, WINHTTP_NO_PROXY_BYPASS
, 0);
472 DWORD nError
= GetLastError();
476 WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions
{};
477 if (pData
->m_bAutoDetect
)
479 AutoProxyOptions
.dwFlags
= WINHTTP_AUTOPROXY_AUTO_DETECT
;
480 AutoProxyOptions
.dwAutoDetectFlags
481 = WINHTTP_AUTO_DETECT_TYPE_DHCP
| WINHTTP_AUTO_DETECT_TYPE_DNS_A
;
483 if (!pData
->m_sAutoConfigUrl
.isEmpty())
485 AutoProxyOptions
.dwFlags
|= WINHTTP_AUTOPROXY_CONFIG_URL
;
486 AutoProxyOptions
.lpszAutoConfigUrl
= o3tl::toW(pData
->m_sAutoConfigUrl
.getStr());
488 // First, try without autologon. According to
489 // https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/web/winhttp/WinhttpProxySample/GetProxy.cpp
490 // autologon prevents caching, and so causes repetitive network traffic.
491 AutoProxyOptions
.fAutoLogonIfChallenged
= FALSE
;
492 WINHTTP_PROXY_INFO ProxyInfo
{};
494 = WinHttpGetProxyForUrl(hInternet
, o3tl::toW(url
.getStr()), &AutoProxyOptions
, &ProxyInfo
);
495 nError
= GetLastError();
496 if (!bResult
&& nError
== ERROR_WINHTTP_LOGIN_FAILURE
)
498 AutoProxyOptions
.fAutoLogonIfChallenged
= TRUE
;
499 bResult
= WinHttpGetProxyForUrl(hInternet
, o3tl::toW(url
.getStr()),
500 &AutoProxyOptions
, &ProxyInfo
);
501 nError
= GetLastError();
503 WinHttpCloseHandle(hInternet
);
506 if (ProxyInfo
.lpszProxyBypass
)
507 GlobalFree(ProxyInfo
.lpszProxyBypass
);
508 if (ProxyInfo
.lpszProxy
)
510 OUString sProxyResult
= o3tl::toU(ProxyInfo
.lpszProxy
);
511 GlobalFree(ProxyInfo
.lpszProxy
);
512 // Get the first of possibly multiple results
513 sProxyResult
= sProxyResult
.getToken(0, ';');
514 sal_Int32 nPortSepPos
= sProxyResult
.indexOf(':');
515 if (nPortSepPos
!= -1)
517 pData
->m_ProxyServer
.nPort
= sProxyResult
.copy(nPortSepPos
+ 1).toInt32();
518 sProxyResult
= sProxyResult
.copy(0, nPortSepPos
);
522 pData
->m_ProxyServer
.nPort
= 0;
524 pData
->m_ProxyServer
.aName
= sProxyResult
;
531 InternetProxyServer
GetPACProxy(const OUString
& rProtocol
, const OUString
& rHost
, sal_Int32 nPort
)
533 GetPACProxyData
aData(rProtocol
, rHost
, nPort
);
535 // WinHTTP only supports http(s), so don't try for other protocols
536 if (!(rProtocol
.equalsIgnoreAsciiCase("http") || rProtocol
.equalsIgnoreAsciiCase("https")))
537 return aData
.m_ProxyServer
;
539 // Only try to get configuration from PAC (with all the overhead, including new thread)
540 // if configured to do so
542 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG aProxyConfig
{};
543 BOOL bResult
= WinHttpGetIEProxyConfigForCurrentUser(&aProxyConfig
);
544 if (aProxyConfig
.lpszProxy
)
545 GlobalFree(aProxyConfig
.lpszProxy
);
546 if (aProxyConfig
.lpszProxyBypass
)
547 GlobalFree(aProxyConfig
.lpszProxyBypass
);
548 // Don't try WPAD if AutoDetection or AutoConfig script URL are not configured
549 if (!bResult
|| !(aProxyConfig
.fAutoDetect
|| aProxyConfig
.lpszAutoConfigUrl
))
550 return aData
.m_ProxyServer
;
551 aData
.m_bAutoDetect
= aProxyConfig
.fAutoDetect
;
552 if (aProxyConfig
.lpszAutoConfigUrl
)
554 aData
.m_sAutoConfigUrl
= o3tl::toU(aProxyConfig
.lpszAutoConfigUrl
);
555 GlobalFree(aProxyConfig
.lpszAutoConfigUrl
);
559 HANDLE hThread
= CreateThread(nullptr, 0, GetPACProxyThread
, &aData
, 0, nullptr);
562 WaitForSingleObject(hThread
, INFINITE
);
563 CloseHandle(hThread
);
565 return aData
.m_ProxyServer
;
570 // Read the settings from the OS which are stored in env vars
572 InternetProxyServer
GetUnixSystemProxy(const OUString
& rProtocol
,
573 const OUString
& /*rHost*/,
576 // TODO this could be improved to read the "no_proxy" env variable
577 InternetProxyServer aProxy
;
578 OUString protocolLower
= rProtocol
.toAsciiLowerCase() + "_proxy";
579 OString protocolLowerStr
= OUStringToOString( protocolLower
, RTL_TEXTENCODING_ASCII_US
);
580 const char* pEnvProxy
= getenv(protocolLowerStr
.getStr());
583 // expecting something like "https://example.ct:80"
584 OUString tmp
= OUString::createFromAscii(pEnvProxy
);
585 if (tmp
.getLength() < (rProtocol
.getLength() + 3))
587 tmp
= tmp
.copy(rProtocol
.getLength() + 3);
588 sal_Int32 x
= tmp
.indexOf(':');
591 int nPort
= tmp
.copy(x
+ 1).toInt32();
594 aProxy
.aName
= tmp
.copy(0, x
);
595 aProxy
.nPort
= nPort
;
599 #endif // else .. _WIN32
602 InternetProxyServer
InternetProxyDecider_Impl::getProxy(
603 const OUString
& rProtocol
,
604 const OUString
& rHost
,
605 sal_Int32 nPort
) const
607 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
609 if ( m_nProxyType
== ProxyType::NoProxy
)
612 return m_aEmptyProxy
;
615 // If get from system
616 if (m_nProxyType
== ProxyType::Automatic
&& !rHost
.isEmpty())
619 InternetProxyServer
aProxy(GetPACProxy(rProtocol
, rHost
, nPort
));
621 InternetProxyServer
aProxy(GetUnixSystemProxy(rProtocol
, rHost
, nPort
));
623 if (!aProxy
.aName
.isEmpty())
627 if ( !rHost
.isEmpty() && !m_aNoProxyList
.empty() )
630 // First, try direct hostname match - #110515#
633 if ( !shouldUseProxy( rHost
, nPort
, false ) )
634 return m_aEmptyProxy
;
637 // Second, try match against full qualified hostname - #104401#
642 if ( ( rHost
.getLength() > 1 ) &&
643 ( rHost
[ 0 ] == '[' ))
645 // host is given as numeric IPv6 address. name resolution
646 // functions need hostname without square brackets.
647 aHost
= rHost
.copy( 1, rHost
.getLength() - 2 );
654 OUString aFullyQualifiedHost
;
655 if ( !m_aHostnames
.get( aHost
, aFullyQualifiedHost
) )
657 // This might be quite expensive (DNS lookup).
658 const osl::SocketAddr
aAddr( aHost
, nPort
);
659 aFullyQualifiedHost
= aAddr
.getHostname().toAsciiLowerCase();
660 m_aHostnames
.put( aHost
, aFullyQualifiedHost
);
663 // Error resolving name? -> fallback.
664 if ( aFullyQualifiedHost
.isEmpty() )
665 aFullyQualifiedHost
= aHost
;
667 if ( aFullyQualifiedHost
!= aHost
)
669 if ( !shouldUseProxy( aFullyQualifiedHost
, nPort
, false ) )
670 return m_aEmptyProxy
;
674 // Third, try match of fully qualified entries in no-proxy list
675 // against full qualified hostname
678 // list: staroffice-doc -> full: xyz.germany.sun.com
679 // in: staroffice-doc.germany.sun.com -> full: xyz.germany.sun.com
682 if ( !shouldUseProxy( aFullyQualifiedHost
, nPort
, true ) )
683 return m_aEmptyProxy
;
686 if ( rProtocol
.toAsciiLowerCase() == "ftp" )
688 if ( !m_aFtpProxy
.aName
.isEmpty() && m_aFtpProxy
.nPort
>= 0 )
691 else if ( rProtocol
.toAsciiLowerCase() == "https" )
693 if ( !m_aHttpsProxy
.aName
.isEmpty() )
694 return m_aHttpsProxy
;
696 else if ( !m_aHttpProxy
.aName
.isEmpty() )
698 // All other protocols use the HTTP proxy.
701 return m_aEmptyProxy
;
705 void SAL_CALL
InternetProxyDecider_Impl::changesOccurred(
706 const util::ChangesEvent
& Event
)
708 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
710 sal_Int32 nCount
= Event
.Changes
.getLength();
713 const util::ElementChange
* pElementChanges
714 = Event
.Changes
.getConstArray();
715 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
717 const util::ElementChange
& rElem
= pElementChanges
[ n
];
719 if ( ( rElem
.Accessor
>>= aKey
) && !aKey
.isEmpty() )
721 if ( aKey
== PROXY_TYPE_KEY
)
724 if ( !( rElem
.Element
>>= tmp
) )
726 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
727 "Error getting config item value!" );
730 m_nProxyType
= static_cast<ProxyType
>(tmp
);
732 else if ( aKey
== NO_PROXY_LIST_KEY
)
734 OUString aNoProxyList
;
735 if ( !( rElem
.Element
>>= aNoProxyList
) )
737 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
738 "Error getting config item value!" );
741 setNoProxyList( aNoProxyList
);
743 else if ( aKey
== HTTP_PROXY_NAME_KEY
)
745 if ( !( rElem
.Element
>>= m_aHttpProxy
.aName
) )
747 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
748 "Error getting config item value!" );
751 else if ( aKey
== HTTP_PROXY_PORT_KEY
)
753 if ( !( rElem
.Element
>>= m_aHttpProxy
.nPort
) )
755 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
756 "Error getting config item value!" );
759 if ( m_aHttpProxy
.nPort
== -1 )
760 m_aHttpProxy
.nPort
= 80; // standard HTTP port.
762 else if ( aKey
== HTTPS_PROXY_NAME_KEY
)
764 if ( !( rElem
.Element
>>= m_aHttpsProxy
.aName
) )
766 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
767 "Error getting config item value!" );
770 else if ( aKey
== HTTPS_PROXY_PORT_KEY
)
772 if ( !( rElem
.Element
>>= m_aHttpsProxy
.nPort
) )
774 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
775 "Error getting config item value!" );
778 if ( m_aHttpsProxy
.nPort
== -1 )
779 m_aHttpsProxy
.nPort
= 443; // standard HTTPS port.
781 else if ( aKey
== FTP_PROXY_NAME_KEY
)
783 if ( !( rElem
.Element
>>= m_aFtpProxy
.aName
) )
785 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
786 "Error getting config item value!" );
789 else if ( aKey
== FTP_PROXY_PORT_KEY
)
791 if ( !( rElem
.Element
>>= m_aFtpProxy
.nPort
) )
793 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
794 "Error getting config item value!" );
804 void SAL_CALL
InternetProxyDecider_Impl::disposing(const lang::EventObject
&)
806 if ( m_xNotifier
.is() )
808 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
810 if ( m_xNotifier
.is() )
816 void InternetProxyDecider_Impl::setNoProxyList(
817 const OUString
& rNoProxyList
)
819 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
821 m_aNoProxyList
.clear();
823 if ( !rNoProxyList
.isEmpty() )
825 // List of connection endpoints hostname[:port],
826 // separated by semicolon. Wildcards allowed.
829 sal_Int32 nEnd
= rNoProxyList
.indexOf( ';' );
830 sal_Int32 nLen
= rNoProxyList
.getLength();
837 OUString aToken
= rNoProxyList
.copy( nPos
, nEnd
- nPos
);
839 if ( !aToken
.isEmpty() )
844 // numerical IPv6 address?
845 bool bIPv6Address
= false;
846 sal_Int32 nClosedBracketPos
= aToken
.indexOf( ']' );
847 if ( nClosedBracketPos
== -1 )
848 nClosedBracketPos
= 0;
852 sal_Int32 nColonPos
= aToken
.indexOf( ':', nClosedBracketPos
);
853 if ( nColonPos
== -1 )
855 // No port given, server pattern equals current token
857 if ( aToken
.indexOf( '*' ) == -1 )
859 // pattern describes exactly one server
867 // Port given, extract server pattern
868 sal_Int32 nAsteriskPos
= aToken
.indexOf( '*' );
869 aPort
= aToken
.copy( nColonPos
+ 1 );
870 if ( nAsteriskPos
< nColonPos
)
872 // pattern describes exactly one server
873 aServer
= aToken
.copy( 0, nColonPos
);
877 OUStringBuffer aFullyQualifiedHost
;
878 if ( !aServer
.isEmpty() )
880 // Remember fully qualified server name if current list
881 // entry specifies exactly one non-fully qualified server
884 // remove square brackets from host name in case it's
885 // a numerical IPv6 address.
887 aServer
= aServer
.copy( 1, aServer
.getLength() - 2 );
889 // This might be quite expensive (DNS lookup).
890 const osl::SocketAddr
aAddr( aServer
, 0 );
891 OUString aTmp
= aAddr
.getHostname().toAsciiLowerCase();
892 if ( aTmp
!= aServer
.toAsciiLowerCase() )
896 aFullyQualifiedHost
.append( "[" );
897 aFullyQualifiedHost
.append( aTmp
);
898 aFullyQualifiedHost
.append( "]" );
902 aFullyQualifiedHost
.append( aTmp
);
904 aFullyQualifiedHost
.append( ":" );
905 aFullyQualifiedHost
.append( aPort
);
909 m_aNoProxyList
.emplace_back( WildCard( aToken
),
910 WildCard( aFullyQualifiedHost
.makeStringAndClear() ) );
916 nEnd
= rNoProxyList
.indexOf( ';', nPos
);
919 while ( nEnd
!= nLen
);
923 } // namespace proxydecider_impl
926 // InternetProxyDecider Implementation.
929 InternetProxyDecider::InternetProxyDecider(
930 const uno::Reference
< uno::XComponentContext
>& rxContext
)
931 : m_xImpl( new proxydecider_impl::InternetProxyDecider_Impl( rxContext
) )
936 InternetProxyDecider::~InternetProxyDecider()
938 // Break circular reference between config listener and notifier.
943 bool InternetProxyDecider::shouldUseProxy( const OUString
& rProtocol
,
944 const OUString
& rHost
,
945 sal_Int32 nPort
) const
947 const InternetProxyServer
& rData
= m_xImpl
->getProxy( rProtocol
,
950 return !rData
.aName
.isEmpty();
954 InternetProxyServer
InternetProxyDecider::getProxy(
955 const OUString
& rProtocol
,
956 const OUString
& rHost
,
957 sal_Int32 nPort
) const
959 return m_xImpl
->getProxy( rProtocol
, rHost
, nPort
);
962 } // namespace ucbhelper
964 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */