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 .
20 #include <sal/config.h>
22 #include <string_view>
27 #include <osl/diagnose.h>
28 #include <osl/mutex.hxx>
29 #include <rtl/ref.hxx>
30 #include <osl/socket.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/configuration/theDefaultProvider.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/util/XChangesListener.hpp>
36 #include <com/sun/star/util/XChangesNotifier.hpp>
37 #include <cppuhelper/implbase.hxx>
38 #include <ucbhelper/proxydecider.hxx>
39 #include <o3tl/string_view.hxx>
42 #include <o3tl/char16_t2wchar_t.hxx>
43 #define WIN32_LEAN_AND_MEAN
48 using namespace com::sun::star
;
49 using namespace ucbhelper
;
51 constexpr OUStringLiteral CONFIG_ROOT_KEY
= u
"org.openoffice.Inet/Settings";
52 constexpr OUStringLiteral PROXY_TYPE_KEY
= u
"ooInetProxyType";
53 constexpr OUStringLiteral NO_PROXY_LIST_KEY
= u
"ooInetNoProxy";
54 constexpr OUStringLiteral HTTP_PROXY_NAME_KEY
= u
"ooInetHTTPProxyName";
55 constexpr OUStringLiteral HTTP_PROXY_PORT_KEY
= u
"ooInetHTTPProxyPort";
56 constexpr OUStringLiteral HTTPS_PROXY_NAME_KEY
= u
"ooInetHTTPSProxyName";
57 constexpr OUStringLiteral HTTPS_PROXY_PORT_KEY
= u
"ooInetHTTPSProxyPort";
58 constexpr OUStringLiteral FTP_PROXY_NAME_KEY
= u
"ooInetFTPProxyName";
59 constexpr OUStringLiteral FTP_PROXY_PORT_KEY
= u
"ooInetFTPProxyPort";
66 namespace proxydecider_impl
71 // A simple case ignoring wildcard matcher.
75 OString m_aWildString
;
78 explicit WildCard( std::u16string_view rWildCard
)
81 rWildCard
, RTL_TEXTENCODING_UTF8
).toAsciiLowerCase() ) {}
83 bool Matches( std::u16string_view rStr
) const;
92 typedef std::pair
< OUString
, OUString
> HostListEntry
;
94 std::deque
< HostListEntry
> m_aHostList
;
97 bool get( std::u16string_view rKey
, OUString
& rValue
) const
99 for (auto const& host
: m_aHostList
)
101 if ( host
.first
== rKey
)
103 rValue
= host
.second
;
110 void put( const OUString
& rKey
, const OUString
& rValue
)
112 static constexpr sal_uInt32 nCapacity
= 256;
114 if ( m_aHostList
.size() == nCapacity
)
115 m_aHostList
.resize( nCapacity
/ 2 );
117 m_aHostList
.push_front( HostListEntry( rKey
, rValue
) );
123 class InternetProxyDecider_Impl
:
124 public cppu::WeakImplHelper
< util::XChangesListener
>
126 // see officecfg/registry/schema/org/openoffice/Inet.xcs for the definition of these values
127 enum class ProxyType
{ NoProxy
, Automatic
, Manual
};
128 mutable osl::Mutex m_aMutex
;
129 InternetProxyServer m_aHttpProxy
;
130 InternetProxyServer m_aHttpsProxy
;
131 InternetProxyServer m_aFtpProxy
;
132 const InternetProxyServer m_aEmptyProxy
;
133 ProxyType m_nProxyType
;
134 uno::Reference
< util::XChangesNotifier
> m_xNotifier
;
135 typedef std::pair
< WildCard
, WildCard
> NoProxyListEntry
;
136 std::vector
< NoProxyListEntry
> m_aNoProxyList
;
137 mutable HostnameCache m_aHostnames
;
140 bool shouldUseProxy( std::u16string_view rHost
,
142 bool bUseFullyQualified
) const;
144 explicit InternetProxyDecider_Impl(
145 const uno::Reference
< uno::XComponentContext
>& rxContext
);
149 InternetProxyServer
getProxy(const OUString
& rProtocol
,
150 const OUString
& rHost
,
151 sal_Int32 nPort
) const;
154 virtual void SAL_CALL
changesOccurred( const util::ChangesEvent
& Event
) override
;
156 // XEventListener ( base of XChangesLisetenr )
157 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) override
;
160 void setNoProxyList( const OUString
& rNoProxyList
);
164 // WildCard Implementation.
167 bool WildCard::Matches( std::u16string_view rString
) const
170 = OUStringToOString( rString
, RTL_TEXTENCODING_UTF8
).toAsciiLowerCase();
171 const char * pStr
= aString
.getStr();
172 const char * pWild
= m_aWildString
.getStr();
177 while ( *pWild
|| flag
)
187 if ( ( *pWild
== '\\' ) && ( ( *( pWild
+ 1 ) == '?' )
188 || ( *( pWild
+ 1 ) == '*') ) )
190 if ( *pWild
!= *pStr
)
201 while ( *pWild
== '*' )
203 if ( *pWild
== '\0' )
208 return ( *pWild
== '\0' );
209 while ( *pStr
&& *pStr
!= *pWild
)
211 if ( *pWild
== '?' ) {
213 while ( *pWild
== '*' )
218 return ( *pWild
== '\0' );
222 if ( *pWild
!= '\0' )
231 return ( *pStr
== '\0' ) && ( *pWild
== '\0' );
235 static bool getConfigStringValue(
236 const uno::Reference
< container::XNameAccess
> & xNameAccess
,
242 if ( !( xNameAccess
->getByName( key
) >>= value
) )
244 OSL_FAIL( "InternetProxyDecider - "
245 "Error getting config item value!" );
249 catch ( lang::WrappedTargetException
const & )
253 catch ( container::NoSuchElementException
const & )
261 static bool getConfigInt32Value(
262 const uno::Reference
< container::XNameAccess
> & xNameAccess
,
268 uno::Any aValue
= xNameAccess
->getByName( key
);
269 if ( aValue
.hasValue() && !( aValue
>>= value
) )
271 OSL_FAIL( "InternetProxyDecider - "
272 "Error getting config item value!" );
276 catch ( lang::WrappedTargetException
const & )
280 catch ( container::NoSuchElementException
const & )
288 // InternetProxyDecider_Impl Implementation.
291 InternetProxyDecider_Impl::InternetProxyDecider_Impl(
292 const uno::Reference
< uno::XComponentContext
>& rxContext
)
293 : m_nProxyType( ProxyType::NoProxy
),
299 // Read proxy configuration from config db.
302 uno::Reference
< lang::XMultiServiceFactory
> xConfigProv
=
303 configuration::theDefaultProvider::get( rxContext
);
305 uno::Sequence
< uno::Any
> aArguments
{ uno::Any(OUString( CONFIG_ROOT_KEY
)) };
306 uno::Reference
< uno::XInterface
> xInterface(
307 xConfigProv
->createInstanceWithArguments(
308 "com.sun.star.configuration.ConfigurationAccess",
311 OSL_ENSURE( xInterface
.is(),
312 "InternetProxyDecider - No config access!" );
314 if ( xInterface
.is() )
316 uno::Reference
< container::XNameAccess
> xNameAccess(
317 xInterface
, uno::UNO_QUERY
);
318 OSL_ENSURE( xNameAccess
.is(),
319 "InternetProxyDecider - No name access!" );
321 if ( xNameAccess
.is() )
323 // *** Proxy type ***
326 xNameAccess
, PROXY_TYPE_KEY
, tmp
);
327 m_nProxyType
= static_cast<ProxyType
>(tmp
);
329 // *** No proxy list ***
330 OUString aNoProxyList
;
331 getConfigStringValue(
332 xNameAccess
, NO_PROXY_LIST_KEY
, aNoProxyList
);
333 setNoProxyList( aNoProxyList
);
336 getConfigStringValue(
337 xNameAccess
, HTTP_PROXY_NAME_KEY
, m_aHttpProxy
.aName
);
339 m_aHttpProxy
.nPort
= -1;
341 xNameAccess
, HTTP_PROXY_PORT_KEY
, m_aHttpProxy
.nPort
);
342 if ( m_aHttpProxy
.nPort
== -1 )
343 m_aHttpProxy
.nPort
= 80; // standard HTTP port.
346 getConfigStringValue(
347 xNameAccess
, HTTPS_PROXY_NAME_KEY
, m_aHttpsProxy
.aName
);
349 m_aHttpsProxy
.nPort
= -1;
351 xNameAccess
, HTTPS_PROXY_PORT_KEY
, m_aHttpsProxy
.nPort
);
352 if ( m_aHttpsProxy
.nPort
== -1 )
353 m_aHttpsProxy
.nPort
= 443; // standard HTTPS port.
356 getConfigStringValue(
357 xNameAccess
, FTP_PROXY_NAME_KEY
, m_aFtpProxy
.aName
);
359 m_aFtpProxy
.nPort
= -1;
361 xNameAccess
, FTP_PROXY_PORT_KEY
, m_aFtpProxy
.nPort
);
364 // Register as listener for config changes.
366 m_xNotifier
.set( xInterface
, uno::UNO_QUERY
);
368 OSL_ENSURE( m_xNotifier
.is(),
369 "InternetProxyDecider - No notifier!" );
371 if ( m_xNotifier
.is() )
372 m_xNotifier
->addChangesListener( this );
375 catch ( uno::Exception
const & )
377 // createInstance, createInstanceWithArguments
378 OSL_FAIL( "InternetProxyDecider - Exception!" );
382 void InternetProxyDecider_Impl::dispose()
384 uno::Reference
< util::XChangesNotifier
> xNotifier
;
386 if ( m_xNotifier
.is() )
388 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
390 if ( m_xNotifier
.is() )
392 xNotifier
= m_xNotifier
;
397 // Do this unguarded!
398 if ( xNotifier
.is() )
399 xNotifier
->removeChangesListener( this );
403 bool InternetProxyDecider_Impl::shouldUseProxy( std::u16string_view rHost
,
405 bool bUseFullyQualified
) const
407 OUStringBuffer aBuffer
;
409 if ( ( rHost
.find( ':' ) != std::u16string_view::npos
) &&
410 ( rHost
[ 0 ] != '[' ) )
412 // host is given as numeric IPv6 address
413 aBuffer
.append( "[" );
414 aBuffer
.append( rHost
);
415 aBuffer
.append( "]" );
419 // host is given either as numeric IPv4 address or non-numeric hostname
420 aBuffer
.append( rHost
);
423 aBuffer
.append( ':' );
424 aBuffer
.append( nPort
);
425 const OUString
aHostAndPort( aBuffer
.makeStringAndClear() );
427 for (auto const& noProxy
: m_aNoProxyList
)
429 if ( bUseFullyQualified
)
431 if ( noProxy
.second
.Matches( aHostAndPort
) )
436 if ( noProxy
.first
.Matches( aHostAndPort
) )
447 struct GetPACProxyData
449 const OUString
& m_rProtocol
;
450 const OUString
& m_rHost
;
452 bool m_bAutoDetect
= false;
453 OUString m_sAutoConfigUrl
;
454 InternetProxyServer m_ProxyServer
;
456 GetPACProxyData(const OUString
& rProtocol
, const OUString
& rHost
, sal_Int32 nPort
)
457 : m_rProtocol(rProtocol
)
464 // Tries to get proxy configuration using WinHttpGetProxyForUrl, which supports Web Proxy Auto-Discovery
465 // (WPAD) protocol and manually configured address to get Proxy Auto-Configuration (PAC) file.
466 // The WinINet/WinHTTP functions cannot correctly run in a STA COM thread, so use a dedicated thread
467 DWORD WINAPI
GetPACProxyThread(_In_ LPVOID lpParameter
)
470 GetPACProxyData
* pData
= static_cast<GetPACProxyData
*>(lpParameter
);
472 OUString
url(pData
->m_rProtocol
+ "://" + pData
->m_rHost
+ ":"
473 + OUString::number(pData
->m_nPort
));
475 HINTERNET hInternet
= WinHttpOpen(L
"Mozilla 5.0", WINHTTP_ACCESS_TYPE_NO_PROXY
,
476 WINHTTP_NO_PROXY_NAME
, WINHTTP_NO_PROXY_BYPASS
, 0);
477 DWORD nError
= GetLastError();
481 WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions
{};
482 if (pData
->m_bAutoDetect
)
484 AutoProxyOptions
.dwFlags
= WINHTTP_AUTOPROXY_AUTO_DETECT
;
485 AutoProxyOptions
.dwAutoDetectFlags
486 = WINHTTP_AUTO_DETECT_TYPE_DHCP
| WINHTTP_AUTO_DETECT_TYPE_DNS_A
;
488 if (!pData
->m_sAutoConfigUrl
.isEmpty())
490 AutoProxyOptions
.dwFlags
|= WINHTTP_AUTOPROXY_CONFIG_URL
;
491 AutoProxyOptions
.lpszAutoConfigUrl
= o3tl::toW(pData
->m_sAutoConfigUrl
.getStr());
493 // First, try without autologon. According to
494 // https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/web/winhttp/WinhttpProxySample/GetProxy.cpp
495 // autologon prevents caching, and so causes repetitive network traffic.
496 AutoProxyOptions
.fAutoLogonIfChallenged
= FALSE
;
497 WINHTTP_PROXY_INFO ProxyInfo
{};
499 = WinHttpGetProxyForUrl(hInternet
, o3tl::toW(url
.getStr()), &AutoProxyOptions
, &ProxyInfo
);
500 nError
= GetLastError();
501 if (!bResult
&& nError
== ERROR_WINHTTP_LOGIN_FAILURE
)
503 AutoProxyOptions
.fAutoLogonIfChallenged
= TRUE
;
504 bResult
= WinHttpGetProxyForUrl(hInternet
, o3tl::toW(url
.getStr()),
505 &AutoProxyOptions
, &ProxyInfo
);
506 nError
= GetLastError();
508 WinHttpCloseHandle(hInternet
);
511 if (ProxyInfo
.lpszProxyBypass
)
512 GlobalFree(ProxyInfo
.lpszProxyBypass
);
513 if (ProxyInfo
.lpszProxy
)
515 OUString
sProxyResult(o3tl::toU(ProxyInfo
.lpszProxy
));
516 GlobalFree(ProxyInfo
.lpszProxy
);
517 // Get the first of possibly multiple results
518 sProxyResult
= sProxyResult
.getToken(0, ';');
519 sal_Int32 nPortSepPos
= sProxyResult
.indexOf(':');
520 if (nPortSepPos
!= -1)
522 pData
->m_ProxyServer
.nPort
= o3tl::toInt32(sProxyResult
.subView(nPortSepPos
+ 1));
523 sProxyResult
= sProxyResult
.copy(0, nPortSepPos
);
527 pData
->m_ProxyServer
.nPort
= 0;
529 pData
->m_ProxyServer
.aName
= sProxyResult
;
536 InternetProxyServer
GetPACProxy(const OUString
& rProtocol
, const OUString
& rHost
, sal_Int32 nPort
)
538 GetPACProxyData
aData(rProtocol
, rHost
, nPort
);
540 // WinHTTP only supports http(s), so don't try for other protocols
541 if (!(rProtocol
.equalsIgnoreAsciiCase("http") || rProtocol
.equalsIgnoreAsciiCase("https")))
542 return aData
.m_ProxyServer
;
544 // Only try to get configuration from PAC (with all the overhead, including new thread)
545 // if configured to do so
547 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG aProxyConfig
{};
548 bool bResult
= WinHttpGetIEProxyConfigForCurrentUser(&aProxyConfig
);
549 if (aProxyConfig
.lpszProxy
)
550 GlobalFree(aProxyConfig
.lpszProxy
);
551 if (aProxyConfig
.lpszProxyBypass
)
552 GlobalFree(aProxyConfig
.lpszProxyBypass
);
553 // Don't try WPAD if AutoDetection or AutoConfig script URL are not configured
554 if (!bResult
|| !(aProxyConfig
.fAutoDetect
|| aProxyConfig
.lpszAutoConfigUrl
))
555 return aData
.m_ProxyServer
;
556 aData
.m_bAutoDetect
= aProxyConfig
.fAutoDetect
;
557 if (aProxyConfig
.lpszAutoConfigUrl
)
559 aData
.m_sAutoConfigUrl
= o3tl::toU(aProxyConfig
.lpszAutoConfigUrl
);
560 GlobalFree(aProxyConfig
.lpszAutoConfigUrl
);
564 HANDLE hThread
= CreateThread(nullptr, 0, GetPACProxyThread
, &aData
, 0, nullptr);
567 WaitForSingleObject(hThread
, INFINITE
);
568 CloseHandle(hThread
);
570 return aData
.m_ProxyServer
;
575 // Read the settings from the OS which are stored in env vars
577 InternetProxyServer
GetUnixSystemProxy(const OUString
& rProtocol
)
579 // TODO this could be improved to read the "no_proxy" env variable
580 InternetProxyServer aProxy
;
581 OUString protocolLower
= rProtocol
.toAsciiLowerCase() + "_proxy";
582 OString protocolLowerStr
= OUStringToOString( protocolLower
, RTL_TEXTENCODING_ASCII_US
);
583 const char* pEnvProxy
= getenv(protocolLowerStr
.getStr());
586 // expecting something like "https://example.ct:80"
587 OUString tmp
= OUString::createFromAscii(pEnvProxy
);
588 if (tmp
.getLength() < (rProtocol
.getLength() + 3))
590 tmp
= tmp
.copy(rProtocol
.getLength() + 3);
591 sal_Int32 x
= tmp
.indexOf(':');
594 int nPort
= o3tl::toInt32(tmp
.subView(x
+ 1));
597 aProxy
.aName
= tmp
.copy(0, x
);
598 aProxy
.nPort
= nPort
;
602 #endif // else .. _WIN32
605 InternetProxyServer
InternetProxyDecider_Impl::getProxy(
606 const OUString
& rProtocol
,
607 const OUString
& rHost
,
608 sal_Int32 nPort
) const
610 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
612 if ( m_nProxyType
== ProxyType::NoProxy
)
615 return m_aEmptyProxy
;
618 // If get from system
619 if (m_nProxyType
== ProxyType::Automatic
&& !rHost
.isEmpty())
622 InternetProxyServer
aProxy(GetPACProxy(rProtocol
, rHost
, nPort
));
624 InternetProxyServer
aProxy(GetUnixSystemProxy(rProtocol
));
626 if (!aProxy
.aName
.isEmpty())
630 if ( !rHost
.isEmpty() && !m_aNoProxyList
.empty() )
633 // First, try direct hostname match - #110515#
636 if ( !shouldUseProxy( rHost
, nPort
, false ) )
637 return m_aEmptyProxy
;
640 // Second, try match against full qualified hostname - #104401#
645 if ( ( rHost
.getLength() > 1 ) &&
646 ( rHost
[ 0 ] == '[' ))
648 // host is given as numeric IPv6 address. name resolution
649 // functions need hostname without square brackets.
650 aHost
= rHost
.copy( 1, rHost
.getLength() - 2 );
657 OUString aFullyQualifiedHost
;
658 if ( !m_aHostnames
.get( aHost
, aFullyQualifiedHost
) )
660 // This might be quite expensive (DNS lookup).
661 const osl::SocketAddr
aAddr( aHost
, nPort
);
662 aFullyQualifiedHost
= aAddr
.getHostname().toAsciiLowerCase();
663 m_aHostnames
.put( aHost
, aFullyQualifiedHost
);
666 // Error resolving name? -> fallback.
667 if ( aFullyQualifiedHost
.isEmpty() )
668 aFullyQualifiedHost
= aHost
;
670 if ( aFullyQualifiedHost
!= aHost
)
672 if ( !shouldUseProxy( aFullyQualifiedHost
, nPort
, false ) )
673 return m_aEmptyProxy
;
677 // Third, try match of fully qualified entries in no-proxy list
678 // against full qualified hostname
681 // list: staroffice-doc -> full: xyz.germany.sun.com
682 // in: staroffice-doc.germany.sun.com -> full: xyz.germany.sun.com
685 if ( !shouldUseProxy( aFullyQualifiedHost
, nPort
, true ) )
686 return m_aEmptyProxy
;
689 if ( rProtocol
.toAsciiLowerCase() == "ftp" )
691 if ( !m_aFtpProxy
.aName
.isEmpty() && m_aFtpProxy
.nPort
>= 0 )
694 else if ( rProtocol
.toAsciiLowerCase() == "https" )
696 if ( !m_aHttpsProxy
.aName
.isEmpty() )
697 return m_aHttpsProxy
;
699 else if ( !m_aHttpProxy
.aName
.isEmpty() )
701 // All other protocols use the HTTP proxy.
704 return m_aEmptyProxy
;
708 void SAL_CALL
InternetProxyDecider_Impl::changesOccurred(
709 const util::ChangesEvent
& Event
)
711 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
713 for ( const util::ElementChange
& rElem
: Event
.Changes
)
716 if ( ( rElem
.Accessor
>>= aKey
) && !aKey
.isEmpty() )
718 if ( aKey
== PROXY_TYPE_KEY
)
721 if ( !( rElem
.Element
>>= tmp
) )
723 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
724 "Error getting config item value!" );
727 m_nProxyType
= static_cast<ProxyType
>(tmp
);
729 else if ( aKey
== NO_PROXY_LIST_KEY
)
731 OUString aNoProxyList
;
732 if ( !( rElem
.Element
>>= aNoProxyList
) )
734 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
735 "Error getting config item value!" );
738 setNoProxyList( aNoProxyList
);
740 else if ( aKey
== HTTP_PROXY_NAME_KEY
)
742 if ( !( rElem
.Element
>>= m_aHttpProxy
.aName
) )
744 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
745 "Error getting config item value!" );
748 else if ( aKey
== HTTP_PROXY_PORT_KEY
)
750 if ( !( rElem
.Element
>>= m_aHttpProxy
.nPort
) )
752 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
753 "Error getting config item value!" );
756 if ( m_aHttpProxy
.nPort
== -1 )
757 m_aHttpProxy
.nPort
= 80; // standard HTTP port.
759 else if ( aKey
== HTTPS_PROXY_NAME_KEY
)
761 if ( !( rElem
.Element
>>= m_aHttpsProxy
.aName
) )
763 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
764 "Error getting config item value!" );
767 else if ( aKey
== HTTPS_PROXY_PORT_KEY
)
769 if ( !( rElem
.Element
>>= m_aHttpsProxy
.nPort
) )
771 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
772 "Error getting config item value!" );
775 if ( m_aHttpsProxy
.nPort
== -1 )
776 m_aHttpsProxy
.nPort
= 443; // standard HTTPS port.
778 else if ( aKey
== FTP_PROXY_NAME_KEY
)
780 if ( !( rElem
.Element
>>= m_aFtpProxy
.aName
) )
782 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
783 "Error getting config item value!" );
786 else if ( aKey
== FTP_PROXY_PORT_KEY
)
788 if ( !( rElem
.Element
>>= m_aFtpProxy
.nPort
) )
790 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
791 "Error getting config item value!" );
800 void SAL_CALL
InternetProxyDecider_Impl::disposing(const lang::EventObject
&)
802 if ( m_xNotifier
.is() )
804 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
806 if ( m_xNotifier
.is() )
812 void InternetProxyDecider_Impl::setNoProxyList(
813 const OUString
& rNoProxyList
)
815 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
817 m_aNoProxyList
.clear();
819 if ( rNoProxyList
.isEmpty() )
822 // List of connection endpoints hostname[:port],
823 // separated by semicolon. Wildcards allowed.
826 sal_Int32 nEnd
= rNoProxyList
.indexOf( ';' );
827 sal_Int32 nLen
= rNoProxyList
.getLength();
834 OUString aToken
= rNoProxyList
.copy( nPos
, nEnd
- nPos
);
836 if ( !aToken
.isEmpty() )
841 // numerical IPv6 address?
842 bool bIPv6Address
= false;
843 sal_Int32 nClosedBracketPos
= aToken
.indexOf( ']' );
844 if ( nClosedBracketPos
== -1 )
845 nClosedBracketPos
= 0;
849 sal_Int32 nColonPos
= aToken
.indexOf( ':', nClosedBracketPos
);
850 if ( nColonPos
== -1 )
852 // No port given, server pattern equals current token
854 if ( aToken
.indexOf( '*' ) == -1 )
856 // pattern describes exactly one server
864 // Port given, extract server pattern
865 sal_Int32 nAsteriskPos
= aToken
.indexOf( '*' );
866 aPort
= aToken
.copy( nColonPos
+ 1 );
867 if ( nAsteriskPos
< nColonPos
)
869 // pattern describes exactly one server
870 aServer
= aToken
.copy( 0, nColonPos
);
874 OUStringBuffer aFullyQualifiedHost
;
875 if ( !aServer
.isEmpty() )
877 // Remember fully qualified server name if current list
878 // entry specifies exactly one non-fully qualified server
881 // remove square brackets from host name in case it's
882 // a numerical IPv6 address.
884 aServer
= aServer
.copy( 1, aServer
.getLength() - 2 );
886 // This might be quite expensive (DNS lookup).
887 const osl::SocketAddr
aAddr( aServer
, 0 );
888 OUString aTmp
= aAddr
.getHostname().toAsciiLowerCase();
889 if ( aTmp
!= aServer
.toAsciiLowerCase() )
893 aFullyQualifiedHost
.append( "[" );
894 aFullyQualifiedHost
.append( aTmp
);
895 aFullyQualifiedHost
.append( "]" );
899 aFullyQualifiedHost
.append( aTmp
);
901 aFullyQualifiedHost
.append( ":" );
902 aFullyQualifiedHost
.append( aPort
);
906 m_aNoProxyList
.emplace_back( WildCard( aToken
),
907 WildCard( aFullyQualifiedHost
) );
913 nEnd
= rNoProxyList
.indexOf( ';', nPos
);
916 while ( nEnd
!= nLen
);
919 } // namespace proxydecider_impl
922 // InternetProxyDecider Implementation.
925 InternetProxyDecider::InternetProxyDecider(
926 const uno::Reference
< uno::XComponentContext
>& rxContext
)
927 : m_xImpl( new proxydecider_impl::InternetProxyDecider_Impl( rxContext
) )
932 InternetProxyDecider::~InternetProxyDecider()
934 // Break circular reference between config listener and notifier.
939 bool InternetProxyDecider::shouldUseProxy( const OUString
& rProtocol
,
940 const OUString
& rHost
,
941 sal_Int32 nPort
) const
943 const InternetProxyServer
& rData
= m_xImpl
->getProxy( rProtocol
,
946 return !rData
.aName
.isEmpty();
950 InternetProxyServer
InternetProxyDecider::getProxy(
951 const OUString
& rProtocol
,
952 const OUString
& rHost
,
953 sal_Int32 nPort
) const
955 return m_xImpl
->getProxy( rProtocol
, rHost
, nPort
);
958 } // namespace ucbhelper
960 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */