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
49 using namespace com::sun::star
;
50 using namespace ucbhelper
;
52 constexpr OUString CONFIG_ROOT_KEY
= u
"org.openoffice.Inet/Settings"_ustr
;
53 constexpr OUString PROXY_TYPE_KEY
= u
"ooInetProxyType"_ustr
;
54 constexpr OUString NO_PROXY_LIST_KEY
= u
"ooInetNoProxy"_ustr
;
55 constexpr OUString HTTP_PROXY_NAME_KEY
= u
"ooInetHTTPProxyName"_ustr
;
56 constexpr OUString HTTP_PROXY_PORT_KEY
= u
"ooInetHTTPProxyPort"_ustr
;
57 constexpr OUString HTTPS_PROXY_NAME_KEY
= u
"ooInetHTTPSProxyName"_ustr
;
58 constexpr OUString HTTPS_PROXY_PORT_KEY
= u
"ooInetHTTPSProxyPort"_ustr
;
65 namespace proxydecider_impl
70 // A simple case ignoring wildcard matcher.
74 OString m_aWildString
;
77 explicit WildCard( std::u16string_view rWildCard
)
80 rWildCard
, RTL_TEXTENCODING_UTF8
).toAsciiLowerCase() ) {}
82 bool Matches( std::u16string_view rStr
) const;
91 typedef std::pair
< OUString
, OUString
> HostListEntry
;
93 std::deque
< HostListEntry
> m_aHostList
;
96 bool get( std::u16string_view rKey
, OUString
& rValue
) const
98 for (auto const& host
: m_aHostList
)
100 if ( host
.first
== rKey
)
102 rValue
= host
.second
;
109 void put( const OUString
& rKey
, const OUString
& rValue
)
111 static constexpr sal_uInt32 nCapacity
= 256;
113 if ( m_aHostList
.size() == nCapacity
)
114 m_aHostList
.resize( nCapacity
/ 2 );
116 m_aHostList
.push_front( HostListEntry( rKey
, rValue
) );
122 class InternetProxyDecider_Impl
:
123 public cppu::WeakImplHelper
< util::XChangesListener
>
125 // see officecfg/registry/schema/org/openoffice/Inet.xcs for the definition of these values
126 enum class ProxyType
{ NoProxy
, Automatic
, Manual
};
127 mutable osl::Mutex m_aMutex
;
128 InternetProxyServer m_aHttpProxy
;
129 InternetProxyServer m_aHttpsProxy
;
130 const InternetProxyServer m_aEmptyProxy
;
131 ProxyType m_nProxyType
;
132 uno::Reference
< util::XChangesNotifier
> m_xNotifier
;
133 typedef std::pair
< WildCard
, WildCard
> NoProxyListEntry
;
134 std::vector
< NoProxyListEntry
> m_aNoProxyList
;
135 mutable HostnameCache m_aHostnames
;
138 bool shouldUseProxy( std::u16string_view rHost
,
140 bool bUseFullyQualified
) const;
142 explicit InternetProxyDecider_Impl(
143 const uno::Reference
< uno::XComponentContext
>& rxContext
);
147 InternetProxyServer
getProxy(const OUString
& rProtocol
,
148 const OUString
& rHost
,
149 sal_Int32 nPort
) const;
152 virtual void SAL_CALL
changesOccurred( const util::ChangesEvent
& Event
) override
;
154 // XEventListener ( base of XChangesLisetenr )
155 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) override
;
158 void setNoProxyList( std::u16string_view rNoProxyList
);
162 // WildCard Implementation.
165 bool WildCard::Matches( std::u16string_view rString
) const
168 = OUStringToOString( rString
, RTL_TEXTENCODING_UTF8
).toAsciiLowerCase();
169 const char * pStr
= aString
.getStr();
170 const char * pWild
= m_aWildString
.getStr();
175 while ( *pWild
|| flag
)
185 if ( ( *pWild
== '\\' ) && ( ( *( pWild
+ 1 ) == '?' )
186 || ( *( pWild
+ 1 ) == '*') ) )
188 if ( *pWild
!= *pStr
)
199 while ( *pWild
== '*' )
201 if ( *pWild
== '\0' )
206 return ( *pWild
== '\0' );
207 while ( *pStr
&& *pStr
!= *pWild
)
209 if ( *pWild
== '?' ) {
211 while ( *pWild
== '*' )
216 return ( *pWild
== '\0' );
220 if ( *pWild
!= '\0' )
229 return ( *pStr
== '\0' ) && ( *pWild
== '\0' );
233 static bool getConfigStringValue(
234 const uno::Reference
< container::XNameAccess
> & xNameAccess
,
240 if ( !( xNameAccess
->getByName( key
) >>= value
) )
242 OSL_FAIL( "InternetProxyDecider - "
243 "Error getting config item value!" );
247 catch ( lang::WrappedTargetException
const & )
251 catch ( container::NoSuchElementException
const & )
259 static bool getConfigInt32Value(
260 const uno::Reference
< container::XNameAccess
> & xNameAccess
,
266 uno::Any aValue
= xNameAccess
->getByName( key
);
267 if ( aValue
.hasValue() && !( aValue
>>= value
) )
269 OSL_FAIL( "InternetProxyDecider - "
270 "Error getting config item value!" );
274 catch ( lang::WrappedTargetException
const & )
278 catch ( container::NoSuchElementException
const & )
286 // InternetProxyDecider_Impl Implementation.
289 InternetProxyDecider_Impl::InternetProxyDecider_Impl(
290 const uno::Reference
< uno::XComponentContext
>& rxContext
)
291 : m_nProxyType( ProxyType::NoProxy
),
297 // Read proxy configuration from config db.
300 uno::Reference
< lang::XMultiServiceFactory
> xConfigProv
=
301 configuration::theDefaultProvider::get( rxContext
);
303 uno::Sequence
< uno::Any
> aArguments
{ uno::Any(CONFIG_ROOT_KEY
) };
304 uno::Reference
< uno::XInterface
> xInterface(
305 xConfigProv
->createInstanceWithArguments(
306 u
"com.sun.star.configuration.ConfigurationAccess"_ustr
,
309 OSL_ENSURE( xInterface
.is(),
310 "InternetProxyDecider - No config access!" );
312 if ( xInterface
.is() )
314 uno::Reference
< container::XNameAccess
> xNameAccess(
315 xInterface
, uno::UNO_QUERY
);
316 OSL_ENSURE( xNameAccess
.is(),
317 "InternetProxyDecider - No name access!" );
319 if ( xNameAccess
.is() )
321 // *** Proxy type ***
324 xNameAccess
, PROXY_TYPE_KEY
, tmp
);
325 m_nProxyType
= static_cast<ProxyType
>(tmp
);
327 // *** No proxy list ***
328 OUString aNoProxyList
;
329 getConfigStringValue(
330 xNameAccess
, NO_PROXY_LIST_KEY
, aNoProxyList
);
331 setNoProxyList( aNoProxyList
);
334 getConfigStringValue(
335 xNameAccess
, HTTP_PROXY_NAME_KEY
, m_aHttpProxy
.aName
);
337 m_aHttpProxy
.nPort
= -1;
339 xNameAccess
, HTTP_PROXY_PORT_KEY
, m_aHttpProxy
.nPort
);
340 if ( m_aHttpProxy
.nPort
== -1 )
341 m_aHttpProxy
.nPort
= 80; // standard HTTP port.
344 getConfigStringValue(
345 xNameAccess
, HTTPS_PROXY_NAME_KEY
, m_aHttpsProxy
.aName
);
347 m_aHttpsProxy
.nPort
= -1;
349 xNameAccess
, HTTPS_PROXY_PORT_KEY
, m_aHttpsProxy
.nPort
);
350 if ( m_aHttpsProxy
.nPort
== -1 )
351 m_aHttpsProxy
.nPort
= 443; // standard HTTPS port.
354 // Register as listener for config changes.
356 m_xNotifier
.set( xInterface
, uno::UNO_QUERY
);
358 OSL_ENSURE( m_xNotifier
.is(),
359 "InternetProxyDecider - No notifier!" );
361 if ( m_xNotifier
.is() )
362 m_xNotifier
->addChangesListener( this );
365 catch ( uno::Exception
const & )
367 // createInstance, createInstanceWithArguments
368 OSL_FAIL( "InternetProxyDecider - Exception!" );
372 void InternetProxyDecider_Impl::dispose()
374 uno::Reference
< util::XChangesNotifier
> xNotifier
;
376 if ( m_xNotifier
.is() )
378 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
380 if ( m_xNotifier
.is() )
382 xNotifier
= m_xNotifier
;
387 // Do this unguarded!
388 if ( xNotifier
.is() )
389 xNotifier
->removeChangesListener( this );
393 bool InternetProxyDecider_Impl::shouldUseProxy( std::u16string_view rHost
,
395 bool bUseFullyQualified
) const
397 OUStringBuffer aBuffer
;
399 if ( ( rHost
.find( ':' ) != std::u16string_view::npos
) &&
400 ( rHost
[ 0 ] != '[' ) )
402 // host is given as numeric IPv6 address
403 aBuffer
.append( OUString::Concat("[") + rHost
+ "]" );
407 // host is given either as numeric IPv4 address or non-numeric hostname
408 aBuffer
.append( rHost
);
411 aBuffer
.append( ":" + OUString::number( nPort
) );
413 for (auto const& noProxy
: m_aNoProxyList
)
415 if ( bUseFullyQualified
)
417 if ( noProxy
.second
.Matches( aBuffer
) )
422 if ( noProxy
.first
.Matches( aBuffer
) )
433 struct GetPACProxyData
435 const OUString
& m_rProtocol
;
436 const OUString
& m_rHost
;
438 bool m_bAutoDetect
= false;
439 OUString m_sAutoConfigUrl
;
440 InternetProxyServer m_ProxyServer
;
442 GetPACProxyData(const OUString
& rProtocol
, const OUString
& rHost
, sal_Int32 nPort
)
443 : m_rProtocol(rProtocol
)
450 // Tries to get proxy configuration using WinHttpGetProxyForUrl, which supports Web Proxy Auto-Discovery
451 // (WPAD) protocol and manually configured address to get Proxy Auto-Configuration (PAC) file.
452 // The WinINet/WinHTTP functions cannot correctly run in a STA COM thread, so use a dedicated thread
453 unsigned __stdcall
GetPACProxyThread(void* lpParameter
)
456 GetPACProxyData
* pData
= static_cast<GetPACProxyData
*>(lpParameter
);
458 OUString
url(pData
->m_rProtocol
+ "://" + pData
->m_rHost
+ ":"
459 + OUString::number(pData
->m_nPort
));
461 HINTERNET hInternet
= WinHttpOpen(L
"Mozilla 5.0", WINHTTP_ACCESS_TYPE_NO_PROXY
,
462 WINHTTP_NO_PROXY_NAME
, WINHTTP_NO_PROXY_BYPASS
, 0);
463 DWORD nError
= GetLastError();
467 WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions
{};
468 if (pData
->m_bAutoDetect
)
470 AutoProxyOptions
.dwFlags
= WINHTTP_AUTOPROXY_AUTO_DETECT
;
471 AutoProxyOptions
.dwAutoDetectFlags
472 = WINHTTP_AUTO_DETECT_TYPE_DHCP
| WINHTTP_AUTO_DETECT_TYPE_DNS_A
;
474 if (!pData
->m_sAutoConfigUrl
.isEmpty())
476 AutoProxyOptions
.dwFlags
|= WINHTTP_AUTOPROXY_CONFIG_URL
;
477 AutoProxyOptions
.lpszAutoConfigUrl
= o3tl::toW(pData
->m_sAutoConfigUrl
.getStr());
479 // First, try without autologon. According to
480 // https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/web/winhttp/WinhttpProxySample/GetProxy.cpp
481 // autologon prevents caching, and so causes repetitive network traffic.
482 AutoProxyOptions
.fAutoLogonIfChallenged
= FALSE
;
483 WINHTTP_PROXY_INFO ProxyInfo
{};
485 = WinHttpGetProxyForUrl(hInternet
, o3tl::toW(url
.getStr()), &AutoProxyOptions
, &ProxyInfo
);
486 nError
= GetLastError();
487 if (!bResult
&& nError
== ERROR_WINHTTP_LOGIN_FAILURE
)
489 AutoProxyOptions
.fAutoLogonIfChallenged
= TRUE
;
490 bResult
= WinHttpGetProxyForUrl(hInternet
, o3tl::toW(url
.getStr()),
491 &AutoProxyOptions
, &ProxyInfo
);
492 nError
= GetLastError();
494 WinHttpCloseHandle(hInternet
);
497 if (ProxyInfo
.lpszProxyBypass
)
498 GlobalFree(ProxyInfo
.lpszProxyBypass
);
499 if (ProxyInfo
.lpszProxy
)
501 OUString
sProxyResult(o3tl::toU(ProxyInfo
.lpszProxy
));
502 GlobalFree(ProxyInfo
.lpszProxy
);
503 // Get the first of possibly multiple results
504 sProxyResult
= sProxyResult
.getToken(0, ';');
505 sal_Int32 nPortSepPos
= sProxyResult
.indexOf(':');
506 if (nPortSepPos
!= -1)
508 pData
->m_ProxyServer
.nPort
= o3tl::toInt32(sProxyResult
.subView(nPortSepPos
+ 1));
509 sProxyResult
= sProxyResult
.copy(0, nPortSepPos
);
513 pData
->m_ProxyServer
.nPort
= 0;
515 pData
->m_ProxyServer
.aName
= sProxyResult
;
522 InternetProxyServer
GetPACProxy(const OUString
& rProtocol
, const OUString
& rHost
, sal_Int32 nPort
)
524 GetPACProxyData
aData(rProtocol
, rHost
, nPort
);
526 // WinHTTP only supports http(s), so don't try for other protocols
527 if (!(rProtocol
.equalsIgnoreAsciiCase("http") || rProtocol
.equalsIgnoreAsciiCase("https")))
528 return aData
.m_ProxyServer
;
530 // Only try to get configuration from PAC (with all the overhead, including new thread)
531 // if configured to do so
533 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG aProxyConfig
{};
534 bool bResult
= WinHttpGetIEProxyConfigForCurrentUser(&aProxyConfig
);
535 if (aProxyConfig
.lpszProxy
)
536 GlobalFree(aProxyConfig
.lpszProxy
);
537 if (aProxyConfig
.lpszProxyBypass
)
538 GlobalFree(aProxyConfig
.lpszProxyBypass
);
539 // Don't try WPAD if AutoDetection or AutoConfig script URL are not configured
540 if (!bResult
|| !(aProxyConfig
.fAutoDetect
|| aProxyConfig
.lpszAutoConfigUrl
))
541 return aData
.m_ProxyServer
;
542 aData
.m_bAutoDetect
= aProxyConfig
.fAutoDetect
;
543 if (aProxyConfig
.lpszAutoConfigUrl
)
545 aData
.m_sAutoConfigUrl
= o3tl::toU(aProxyConfig
.lpszAutoConfigUrl
);
546 GlobalFree(aProxyConfig
.lpszAutoConfigUrl
);
550 HANDLE hThread
= reinterpret_cast<HANDLE
>(
551 _beginthreadex(nullptr, 0, GetPACProxyThread
, &aData
, 0, nullptr));
554 WaitForSingleObject(hThread
, INFINITE
);
555 CloseHandle(hThread
);
557 return aData
.m_ProxyServer
;
562 // Read the settings from the OS which are stored in env vars
564 InternetProxyServer
GetUnixSystemProxy(const OUString
& rProtocol
)
566 // TODO this could be improved to read the "no_proxy" env variable
567 InternetProxyServer aProxy
;
568 OUString protocolLower
= rProtocol
.toAsciiLowerCase() + "_proxy";
569 OString protocolLowerStr
= OUStringToOString( protocolLower
, RTL_TEXTENCODING_ASCII_US
);
570 const char* pEnvProxy
= getenv(protocolLowerStr
.getStr());
573 // expecting something like "https://example.ct:80"
574 OUString tmp
= OUString::createFromAscii(pEnvProxy
);
575 if (tmp
.getLength() < (rProtocol
.getLength() + 3))
577 sal_Int32 x
= tmp
.indexOf("://");
578 sal_Int32 at
= tmp
.indexOf('@', x
== -1 ? 0 : x
+ 3);
579 x
= tmp
.indexOf(':', at
== -1 ? x
== -1 ? 0 : x
+ 3 : at
+ 1);
582 int nPort
= o3tl::toInt32(tmp
.subView(x
+ 1));
585 aProxy
.aName
= tmp
.copy(0, x
);
586 aProxy
.nPort
= nPort
;
590 #endif // else .. _WIN32
593 InternetProxyServer
InternetProxyDecider_Impl::getProxy(
594 const OUString
& rProtocol
,
595 const OUString
& rHost
,
596 sal_Int32 nPort
) const
598 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
600 if ( m_nProxyType
== ProxyType::NoProxy
)
603 return m_aEmptyProxy
;
606 // If get from system
607 if (m_nProxyType
== ProxyType::Automatic
&& !rHost
.isEmpty())
610 InternetProxyServer
aProxy(GetPACProxy(rProtocol
, rHost
, nPort
));
612 InternetProxyServer
aProxy(GetUnixSystemProxy(rProtocol
));
614 if (!aProxy
.aName
.isEmpty())
618 if ( !rHost
.isEmpty() && !m_aNoProxyList
.empty() )
621 // First, try direct hostname match - #110515#
624 if ( !shouldUseProxy( rHost
, nPort
, false ) )
625 return m_aEmptyProxy
;
628 // Second, try match against full qualified hostname - #104401#
633 if ( ( rHost
.getLength() > 1 ) &&
634 ( rHost
[ 0 ] == '[' ))
636 // host is given as numeric IPv6 address. name resolution
637 // functions need hostname without square brackets.
638 aHost
= rHost
.copy( 1, rHost
.getLength() - 2 );
645 OUString aFullyQualifiedHost
;
646 if ( !m_aHostnames
.get( aHost
, aFullyQualifiedHost
) )
648 // This might be quite expensive (DNS lookup).
649 const osl::SocketAddr
aAddr( aHost
, nPort
);
650 aFullyQualifiedHost
= aAddr
.getHostname().toAsciiLowerCase();
651 m_aHostnames
.put( aHost
, aFullyQualifiedHost
);
654 // Error resolving name? -> fallback.
655 if ( aFullyQualifiedHost
.isEmpty() )
656 aFullyQualifiedHost
= aHost
;
658 if ( aFullyQualifiedHost
!= aHost
)
660 if ( !shouldUseProxy( aFullyQualifiedHost
, nPort
, false ) )
661 return m_aEmptyProxy
;
665 // Third, try match of fully qualified entries in no-proxy list
666 // against full qualified hostname
669 // list: staroffice-doc -> full: xyz.germany.sun.com
670 // in: staroffice-doc.germany.sun.com -> full: xyz.germany.sun.com
673 if ( !shouldUseProxy( aFullyQualifiedHost
, nPort
, true ) )
674 return m_aEmptyProxy
;
677 if (rProtocol
.toAsciiLowerCase() == "https")
679 if ( !m_aHttpsProxy
.aName
.isEmpty() )
680 return m_aHttpsProxy
;
682 else if ( !m_aHttpProxy
.aName
.isEmpty() )
684 // All other protocols use the HTTP proxy.
687 return m_aEmptyProxy
;
691 void SAL_CALL
InternetProxyDecider_Impl::changesOccurred(
692 const util::ChangesEvent
& Event
)
694 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
696 for ( const util::ElementChange
& rElem
: Event
.Changes
)
699 if ( ( rElem
.Accessor
>>= aKey
) && !aKey
.isEmpty() )
701 if ( aKey
== PROXY_TYPE_KEY
)
704 if ( !( rElem
.Element
>>= tmp
) )
706 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
707 "Error getting config item value!" );
710 m_nProxyType
= static_cast<ProxyType
>(tmp
);
712 else if ( aKey
== NO_PROXY_LIST_KEY
)
714 OUString aNoProxyList
;
715 if ( !( rElem
.Element
>>= aNoProxyList
) )
717 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
718 "Error getting config item value!" );
721 setNoProxyList( aNoProxyList
);
723 else if ( aKey
== HTTP_PROXY_NAME_KEY
)
725 if ( !( rElem
.Element
>>= m_aHttpProxy
.aName
) )
727 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
728 "Error getting config item value!" );
731 else if ( aKey
== HTTP_PROXY_PORT_KEY
)
733 if ( !( rElem
.Element
>>= m_aHttpProxy
.nPort
) )
735 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
736 "Error getting config item value!" );
739 if ( m_aHttpProxy
.nPort
== -1 )
740 m_aHttpProxy
.nPort
= 80; // standard HTTP port.
742 else if ( aKey
== HTTPS_PROXY_NAME_KEY
)
744 if ( !( rElem
.Element
>>= m_aHttpsProxy
.aName
) )
746 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
747 "Error getting config item value!" );
750 else if ( aKey
== HTTPS_PROXY_PORT_KEY
)
752 if ( !( rElem
.Element
>>= m_aHttpsProxy
.nPort
) )
754 OSL_FAIL( "InternetProxyDecider - changesOccurred - "
755 "Error getting config item value!" );
758 if ( m_aHttpsProxy
.nPort
== -1 )
759 m_aHttpsProxy
.nPort
= 443; // standard HTTPS port.
767 void SAL_CALL
InternetProxyDecider_Impl::disposing(const lang::EventObject
&)
769 if ( m_xNotifier
.is() )
771 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
773 if ( m_xNotifier
.is() )
779 void InternetProxyDecider_Impl::setNoProxyList(
780 std::u16string_view rNoProxyList
)
782 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
784 m_aNoProxyList
.clear();
786 if ( rNoProxyList
.empty() )
789 // List of connection endpoints hostname[:port],
790 // separated by semicolon. Wildcards allowed.
793 size_t nEnd
= rNoProxyList
.find( ';' );
794 size_t nLen
= rNoProxyList
.size();
798 if ( nEnd
== std::u16string_view::npos
)
801 OUString
aToken( rNoProxyList
.substr( nPos
, nEnd
- nPos
) );
803 if ( !aToken
.isEmpty() )
808 // numerical IPv6 address?
809 bool bIPv6Address
= false;
810 sal_Int32 nClosedBracketPos
= aToken
.indexOf( ']' );
811 if ( nClosedBracketPos
== -1 )
812 nClosedBracketPos
= 0;
816 sal_Int32 nColonPos
= aToken
.indexOf( ':', nClosedBracketPos
);
817 if ( nColonPos
== -1 )
819 // No port given, server pattern equals current token
821 if ( aToken
.indexOf( '*' ) == -1 )
823 // pattern describes exactly one server
831 // Port given, extract server pattern
832 sal_Int32 nAsteriskPos
= aToken
.indexOf( '*' );
833 aPort
= aToken
.copy( nColonPos
+ 1 );
834 if ( nAsteriskPos
< nColonPos
)
836 // pattern describes exactly one server
837 aServer
= aToken
.copy( 0, nColonPos
);
841 OUStringBuffer aFullyQualifiedHost
;
842 if ( !aServer
.isEmpty() )
844 // Remember fully qualified server name if current list
845 // entry specifies exactly one non-fully qualified server
848 // remove square brackets from host name in case it's
849 // a numerical IPv6 address.
851 aServer
= aServer
.copy( 1, aServer
.getLength() - 2 );
853 // This might be quite expensive (DNS lookup).
854 const osl::SocketAddr
aAddr( aServer
, 0 );
855 OUString aTmp
= aAddr
.getHostname().toAsciiLowerCase();
856 if ( aTmp
!= aServer
.toAsciiLowerCase() )
859 aFullyQualifiedHost
.append( "[" + aTmp
+ "]" );
861 aFullyQualifiedHost
.append( aTmp
);
862 aFullyQualifiedHost
.append( ":" + aPort
);
866 m_aNoProxyList
.emplace_back( WildCard( aToken
),
867 WildCard( aFullyQualifiedHost
) );
873 nEnd
= rNoProxyList
.find( ';', nPos
);
876 while ( nEnd
!= nLen
);
879 } // namespace proxydecider_impl
882 // InternetProxyDecider Implementation.
885 InternetProxyDecider::InternetProxyDecider(
886 const uno::Reference
< uno::XComponentContext
>& rxContext
)
887 : m_xImpl( new proxydecider_impl::InternetProxyDecider_Impl( rxContext
) )
892 InternetProxyDecider::~InternetProxyDecider()
894 // Break circular reference between config listener and notifier.
899 OUString
InternetProxyDecider::getProxy(
900 const OUString
& rProtocol
,
901 const OUString
& rHost
,
902 sal_Int32 nPort
) const
904 InternetProxyServer
ret(m_xImpl
->getProxy(rProtocol
, rHost
, nPort
));
906 if (ret
.aName
.isEmpty() || ret
.nPort
== -1)
911 return ret
.aName
+ ":" + OUString::number(ret
.nPort
);
914 } // namespace ucbhelper
916 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */