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