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 <cppuhelper/supportsservice.hxx>
21 #include "rtl/ustrbuf.hxx"
23 #include "wininetbackend.hxx"
26 #pragma warning(push, 1)
30 #include <sal/alloca.h>
35 #define WININET_DLL_NAME "wininet.dll"
36 #define EQUAL_SIGN '='
39 #define SEMI_COLON ';'
46 Library(HMODULE theModule
): module(theModule
) {}
48 ~Library() { if (module
) FreeLibrary(module
); }
65 ProxyEntry
ReadProxyEntry(const OUString
& aProxy
, sal_Int32
& i
)
67 ProxyEntry aProxyEntry
;
69 aProxyEntry
.Server
= aProxy
.getToken( 0, COLON
, i
);
71 aProxyEntry
.Port
= aProxy
.getToken( 0, COLON
, i
);
76 ProxyEntry
FindProxyEntry(const OUString
& aProxyList
, const OUString
& aType
)
82 // get the next token, e.g. ftp=server:port
83 OUString nextToken
= aProxyList
.getToken( 0, SPACE
, nIndex
);
85 // split the next token again into the parts separated
86 // through '=', e.g. ftp=server:port -> ftp and server:port
88 if( nextToken
.indexOf( EQUAL_SIGN
) > -1 )
90 if( aType
.equals( nextToken
.getToken( 0, EQUAL_SIGN
, i
) ) )
91 return ReadProxyEntry(nextToken
, i
);
93 else if( aType
.isEmpty())
94 return ReadProxyEntry(nextToken
, i
);
96 } while ( nIndex
>= 0 );
101 } // end private namespace
105 WinInetBackend::WinInetBackend()
107 Library
hWinInetDll( LoadLibrary( WININET_DLL_NAME
) );
108 if( hWinInetDll
.module
)
110 typedef BOOL ( WINAPI
*InternetQueryOption_Proc_T
)( HINTERNET
, DWORD
, LPVOID
, LPDWORD
);
112 InternetQueryOption_Proc_T lpfnInternetQueryOption
=
113 reinterpret_cast< InternetQueryOption_Proc_T
>(
114 GetProcAddress( hWinInetDll
.module
, "InternetQueryOptionA" ) );
115 if (lpfnInternetQueryOption
)
117 // Some Windows versions would fail the InternetQueryOption call
118 // with ERROR_OUTOFMEMORY when the initial dwLength were zero (and
119 // are apparently fine with the initial sizeof (INTERNET_PROXY_INFO)
120 // and need no reallocation), while other versions fail with
121 // ERROR_INSUFFICIENT_BUFFER upon that initial dwLength and need a
123 INTERNET_PROXY_INFO pi
;
124 LPINTERNET_PROXY_INFO lpi
= &pi
;
125 DWORD dwLength
= sizeof (INTERNET_PROXY_INFO
);
126 BOOL ok
= lpfnInternetQueryOption(
128 INTERNET_OPTION_PROXY
,
133 DWORD err
= GetLastError();
134 if (err
== ERROR_INSUFFICIENT_BUFFER
)
136 // allocate sufficient space on the heap
137 // insufficient space on the heap results
138 // in a stack overflow exception, we assume
139 // this never happens, because of the relatively
140 // small amount of memory we need
141 // alloca is nice because it is fast and we don't
142 // have to free the allocated memory, it will be
143 // automatically done
144 lpi
= reinterpret_cast< LPINTERNET_PROXY_INFO
>(
145 alloca( dwLength
) );
146 ok
= lpfnInternetQueryOption(
148 INTERNET_OPTION_PROXY
,
153 err
= GetLastError();
160 "InternetQueryOption INTERNET_OPTION_PROXY"
161 " GetLastError=" << err
);
166 // if a proxy is disabled, InternetQueryOption returns
167 // an empty proxy list, so we don't have to check if
168 // proxy is enabled or not
170 OUString aProxyList
= OUString::createFromAscii( lpi
->lpszProxy
);
171 OUString aProxyBypassList
= OUString::createFromAscii( lpi
->lpszProxyBypass
);
173 // override default for ProxyType, which is "0" meaning "No proxies".
174 sal_Int32 nProperties
= 1;
176 valueProxyType_
.IsPresent
= true;
177 valueProxyType_
.Value
<<= nProperties
;
179 // fill proxy bypass list
180 if( aProxyBypassList
.getLength() > 0 )
182 OUStringBuffer aReverseList
;
183 sal_Int32 nIndex
= 0;
186 OUString aToken
= aProxyBypassList
.getToken( 0, SPACE
, nIndex
);
187 if ( aProxyList
.indexOf( aToken
) == -1 )
189 if ( aReverseList
.getLength() )
191 aReverseList
.insert( 0, sal_Unicode( SEMI_COLON
) );
192 aReverseList
.insert( 0, aToken
);
195 aReverseList
= aToken
;
198 while ( nIndex
>= 0 );
200 aProxyBypassList
= aReverseList
.makeStringAndClear();
202 valueNoProxy_
.IsPresent
= true;
203 valueNoProxy_
.Value
<<= aProxyBypassList
.replace( SPACE
, SEMI_COLON
);
206 if( aProxyList
.getLength() > 0 )
209 // this implementation follows the algorithm
210 // of the internet explorer
211 // if there are type-dependent proxy settings
212 // and type independent proxy settings in the
213 // registry the internet explorer chooses the
214 // type independent proxy for all settings
215 // e.g. imagine the following registry entry
216 // ftp=server:port;http=server:port;server:port
217 // the last token server:port is type independent
218 // so the ie chooses this proxy server
220 // if there is no port specified for a type independent
221 // server the ie uses the port of an http server if
222 // there is one and it has a port
225 ProxyEntry aTypeIndepProxy
= FindProxyEntry( aProxyList
, OUString());
226 ProxyEntry aHttpProxy
= FindProxyEntry( aProxyList
, OUString(
228 ProxyEntry aHttpsProxy
= FindProxyEntry( aProxyList
, OUString(
231 ProxyEntry aFtpProxy
= FindProxyEntry( aProxyList
, OUString(
234 if( aTypeIndepProxy
.Server
.getLength() )
236 aHttpProxy
.Server
= aTypeIndepProxy
.Server
;
237 aHttpsProxy
.Server
= aTypeIndepProxy
.Server
;
238 aFtpProxy
.Server
= aTypeIndepProxy
.Server
;
240 if( aTypeIndepProxy
.Port
.getLength() )
242 aHttpProxy
.Port
= aTypeIndepProxy
.Port
;
243 aHttpsProxy
.Port
= aTypeIndepProxy
.Port
;
244 aFtpProxy
.Port
= aTypeIndepProxy
.Port
;
248 aFtpProxy
.Port
= aHttpProxy
.Port
;
249 aHttpsProxy
.Port
= aHttpProxy
.Port
;
254 if( aHttpProxy
.Server
.getLength() > 0 )
256 valueHttpProxyName_
.IsPresent
= true;
257 valueHttpProxyName_
.Value
<<= aHttpProxy
.Server
;
261 if( aHttpProxy
.Port
.getLength() > 0 )
263 valueHttpProxyPort_
.IsPresent
= true;
264 valueHttpProxyPort_
.Value
<<= aHttpProxy
.Port
.toInt32();
268 if( aHttpsProxy
.Server
.getLength() > 0 )
270 valueHttpsProxyName_
.IsPresent
= true;
271 valueHttpsProxyName_
.Value
<<= aHttpsProxy
.Server
;
275 if( aHttpsProxy
.Port
.getLength() > 0 )
277 valueHttpsProxyPort_
.IsPresent
= true;
278 valueHttpsProxyPort_
.Value
<<= aHttpsProxy
.Port
.toInt32();
282 if( aFtpProxy
.Server
.getLength() > 0 )
284 valueFtpProxyName_
.IsPresent
= true;
285 valueFtpProxyName_
.Value
<<= aFtpProxy
.Server
;
289 if( aFtpProxy
.Port
.getLength() > 0 )
291 valueFtpProxyPort_
.IsPresent
= true;
292 valueFtpProxyPort_
.Value
<<= aFtpProxy
.Port
.toInt32();
301 WinInetBackend::~WinInetBackend()
307 WinInetBackend
* WinInetBackend::createInstance()
309 return new WinInetBackend
;
314 void WinInetBackend::setPropertyValue(
315 OUString
const &, css::uno::Any
const &)
317 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
318 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
319 css::uno::RuntimeException
)
321 throw css::lang::IllegalArgumentException(
323 "setPropertyValue not supported"),
324 static_cast< cppu::OWeakObject
* >(this), -1);
327 css::uno::Any
WinInetBackend::getPropertyValue(
328 OUString
const & PropertyName
)
330 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
331 css::uno::RuntimeException
)
333 if ( PropertyName
== "ooInetFTPProxyName" )
335 return css::uno::makeAny(valueFtpProxyName_
);
336 } else if ( PropertyName
== "ooInetFTPProxyPort" )
338 return css::uno::makeAny(valueFtpProxyPort_
);
339 } else if ( PropertyName
== "ooInetHTTPProxyName" )
341 return css::uno::makeAny(valueHttpProxyName_
);
342 } else if ( PropertyName
== "ooInetHTTPProxyPort" )
344 return css::uno::makeAny(valueHttpProxyPort_
);
345 } else if ( PropertyName
== "ooInetHTTPSProxyName" )
347 return css::uno::makeAny(valueHttpsProxyName_
);
348 } else if ( PropertyName
== "ooInetHTTPSProxyPort" )
350 return css::uno::makeAny(valueHttpsProxyPort_
);
351 } else if ( PropertyName
== "ooInetNoProxy" )
353 return css::uno::makeAny(valueNoProxy_
);
354 } else if ( PropertyName
== "ooInetProxyType" )
356 return css::uno::makeAny(valueProxyType_
);
358 throw css::beans::UnknownPropertyException(
359 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
365 OUString SAL_CALL
WinInetBackend::getBackendName() {
366 return OUString("com.sun.star.comp.configuration.backend.WinInetBackend") ;
371 OUString SAL_CALL
WinInetBackend::getImplementationName()
372 throw (uno::RuntimeException
)
374 return getBackendName() ;
377 uno::Sequence
<OUString
> SAL_CALL
WinInetBackend::getBackendServiceNames()
379 uno::Sequence
<OUString
> aServiceNameList(1);
380 aServiceNameList
[0] = "com.sun.star.configuration.backend.WinInetBackend";
382 return aServiceNameList
;
385 sal_Bool SAL_CALL
WinInetBackend::supportsService(const OUString
& aServiceName
)
386 throw (uno::RuntimeException
)
388 return cppu::supportsService(this, aServiceName
);
391 uno::Sequence
<OUString
> SAL_CALL
WinInetBackend::getSupportedServiceNames()
392 throw (uno::RuntimeException
)
394 return getBackendServiceNames() ;
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */