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