xref: /AOO41X/main/shell/source/backends/wininetbe/wininetbackend.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_shell.hxx"
30 
31 #include "rtl/ustrbuf.hxx"
32 
33 #include "wininetbackend.hxx"
34 
35 #if defined _MSC_VER
36 #pragma warning(push, 1)
37 #endif
38 #include <windows.h>
39 #include <wininet.h>
40 #include <sal/alloca.h>
41 #if defined _MSC_VER
42 #pragma warning(pop)
43 #endif
44 
45 #define WININET_DLL_NAME "wininet.dll"
46 #define EQUAL_SIGN '='
47 #define COLON      ':'
48 #define SPACE      ' '
49 #define SEMI_COLON ';'
50 
51 namespace {
52 
53 struct Library {
54     HMODULE module;
55 
56     Library(HMODULE theModule): module(theModule) {}
57 
58     ~Library() { if (module) FreeLibrary(module); }
59 };
60 
61 }
62 
63 typedef struct
64 {
65     rtl::OUString Server;
66     rtl::OUString Port;
67 } ProxyEntry;
68 
69 //------------------------------------------------------------------------
70 // helper functions
71 //------------------------------------------------------------------------
72 
73 namespace // private
74 {
75     ProxyEntry ReadProxyEntry(const rtl::OUString& aProxy, sal_Int32& i)
76     {
77         ProxyEntry aProxyEntry;
78 
79         aProxyEntry.Server = aProxy.getToken( 0, COLON, i );
80         if ( i > -1 )
81             aProxyEntry.Port = aProxy.getToken( 0, COLON, i );
82 
83         return aProxyEntry;
84     }
85 
86     ProxyEntry FindProxyEntry(const rtl::OUString& aProxyList, const rtl::OUString& aType)
87     {
88         sal_Int32 nIndex = 0;
89 
90         do
91         {
92             // get the next token, e.g. ftp=server:port
93             rtl::OUString nextToken = aProxyList.getToken( 0, SPACE, nIndex );
94 
95             // split the next token again into the parts separated
96             // through '=', e.g. ftp=server:port -> ftp and server:port
97             sal_Int32 i = 0;
98             if( nextToken.indexOf( EQUAL_SIGN ) > -1 )
99             {
100                 if( aType.equals( nextToken.getToken( 0, EQUAL_SIGN, i ) ) )
101                     return ReadProxyEntry(nextToken, i);
102             }
103             else if( aType.getLength() == 0)
104                 return ReadProxyEntry(nextToken, i);
105 
106         } while ( nIndex >= 0 );
107 
108         return ProxyEntry();
109     }
110 
111 } // end private namespace
112 
113 //------------------------------------------------------------------------------
114 
115 WinInetBackend::WinInetBackend()
116 {
117     Library hWinInetDll( LoadLibrary( WININET_DLL_NAME ) );
118     if( hWinInetDll.module )
119     {
120         typedef BOOL ( WINAPI *InternetQueryOption_Proc_T )( HINTERNET, DWORD, LPVOID, LPDWORD );
121 
122         InternetQueryOption_Proc_T lpfnInternetQueryOption =
123             reinterpret_cast< InternetQueryOption_Proc_T >(
124                 GetProcAddress( hWinInetDll.module, "InternetQueryOptionA" ) );
125         if (lpfnInternetQueryOption)
126         {
127             LPINTERNET_PROXY_INFO lpi = NULL;
128 
129             // query for the neccessary space
130             DWORD dwLength = 0;
131             BOOL bRet = lpfnInternetQueryOption(
132                 NULL,
133                 INTERNET_OPTION_PROXY,
134                 (LPVOID)lpi,
135                 &dwLength );
136 
137             // allocate sufficient space on the heap
138             // insufficient space on the heap results
139             // in a stack overflow exception, we assume
140             // this never happens, because of the relatively
141             // small amount of memory we need
142             // alloca is nice because it is fast and we don't
143             // have to free the allocated memory, it will be
144             // automatically done
145             lpi = reinterpret_cast< LPINTERNET_PROXY_INFO >(
146                 alloca( dwLength ) );
147 
148             bRet = lpfnInternetQueryOption(
149                 NULL,
150                 INTERNET_OPTION_PROXY,
151                 (LPVOID)lpi,
152                 &dwLength );
153 
154             // if a proxy is disabled, InternetQueryOption returns
155             // an empty proxy list, so we don't have to check if
156             // proxy is enabled or not
157 
158             rtl::OUString aProxyList       = rtl::OUString::createFromAscii( lpi->lpszProxy );
159             rtl::OUString aProxyBypassList = rtl::OUString::createFromAscii( lpi->lpszProxyBypass );
160 
161             // override default for ProxyType, which is "0" meaning "No proxies".
162             sal_Int32 nProperties = 1;
163 
164             valueProxyType_.IsPresent = true;
165             valueProxyType_.Value <<= nProperties;
166 
167             // fill proxy bypass list
168             if( aProxyBypassList.getLength() > 0 )
169             {
170                 rtl::OUStringBuffer aReverseList;
171                 sal_Int32 nIndex = 0;
172                 do
173                 {
174                     rtl::OUString aToken = aProxyBypassList.getToken( 0, SPACE, nIndex );
175                     if ( aProxyList.indexOf( aToken ) == -1 )
176                     {
177                         if ( aReverseList.getLength() )
178                         {
179                             aReverseList.insert( 0, sal_Unicode( SEMI_COLON ) );
180                             aReverseList.insert( 0, aToken );
181                         }
182                         else
183                             aReverseList = aToken;
184                     }
185                 }
186                 while ( nIndex >= 0 );
187 
188                 aProxyBypassList = aReverseList.makeStringAndClear();
189 
190                 valueNoProxy_.IsPresent = true;
191                 valueNoProxy_.Value <<= aProxyBypassList.replace( SPACE, SEMI_COLON );
192             }
193 
194             if( aProxyList.getLength() > 0 )
195             {
196                 //-------------------------------------------------
197                 // this implementation follows the algorithm
198                 // of the internet explorer
199                 // if there are type-dependent proxy settings
200                 // and type independent proxy settings in the
201                 // registry the internet explorer chooses the
202                 // type independent proxy for all settings
203                 // e.g. imagine the following registry entry
204                 // ftp=server:port;http=server:port;server:port
205                 // the last token server:port is type independent
206                 // so the ie chooses this proxy server
207 
208                 // if there is no port specified for a type independent
209                 // server the ie uses the port of an http server if
210                 // there is one and it has a port
211                 //-------------------------------------------------
212 
213                 ProxyEntry aTypeIndepProxy = FindProxyEntry( aProxyList, rtl::OUString());
214                 ProxyEntry aHttpProxy = FindProxyEntry( aProxyList, rtl::OUString(
215                     RTL_CONSTASCII_USTRINGPARAM( "http" ) ) );
216                 ProxyEntry aHttpsProxy  = FindProxyEntry( aProxyList, rtl::OUString(
217                     RTL_CONSTASCII_USTRINGPARAM( "https" ) ) );
218 
219                 ProxyEntry aFtpProxy  = FindProxyEntry( aProxyList, rtl::OUString(
220                     RTL_CONSTASCII_USTRINGPARAM( "ftp" ) ) );
221 
222                 if( aTypeIndepProxy.Server.getLength() )
223                 {
224                     aHttpProxy.Server = aTypeIndepProxy.Server;
225                     aHttpsProxy.Server  = aTypeIndepProxy.Server;
226                     aFtpProxy.Server  = aTypeIndepProxy.Server;
227 
228                     if( aTypeIndepProxy.Port.getLength() )
229                     {
230                         aHttpProxy.Port = aTypeIndepProxy.Port;
231                         aHttpsProxy.Port  = aTypeIndepProxy.Port;
232                         aFtpProxy.Port  = aTypeIndepProxy.Port;
233                     }
234                     else
235                     {
236                         aFtpProxy.Port  = aHttpProxy.Port;
237                         aHttpsProxy.Port  = aHttpProxy.Port;
238                     }
239                 }
240 
241                 // http proxy name
242                 if( aHttpProxy.Server.getLength() > 0 )
243                 {
244                     valueHttpProxyName_.IsPresent = true;
245                     valueHttpProxyName_.Value <<= aHttpProxy.Server;
246                 }
247 
248                 // http proxy port
249                 if( aHttpProxy.Port.getLength() > 0 )
250                 {
251                     valueHttpProxyPort_.IsPresent = true;
252                     valueHttpProxyPort_.Value <<= aHttpProxy.Port.toInt32();
253                 }
254 
255                 // https proxy name
256                 if( aHttpsProxy.Server.getLength() > 0 )
257                 {
258                     valueHttpsProxyName_.IsPresent = true;
259                     valueHttpsProxyName_.Value <<= aHttpsProxy.Server;
260                 }
261 
262                 // https proxy port
263                 if( aHttpsProxy.Port.getLength() > 0 )
264                 {
265                     valueHttpsProxyPort_.IsPresent = true;
266                     valueHttpsProxyPort_.Value <<= aHttpsProxy.Port.toInt32();
267                 }
268 
269                 // ftp proxy name
270                 if( aFtpProxy.Server.getLength() > 0 )
271                 {
272                     valueFtpProxyName_.IsPresent = true;
273                     valueFtpProxyName_.Value <<= aFtpProxy.Server;
274                 }
275 
276                 // ftp proxy port
277                 if( aFtpProxy.Port.getLength() > 0 )
278                 {
279                     valueFtpProxyPort_.IsPresent = true;
280                     valueFtpProxyPort_.Value <<= aFtpProxy.Port.toInt32();
281                 }
282             }
283         }
284     }
285 }
286 
287 //------------------------------------------------------------------------------
288 
289 WinInetBackend::~WinInetBackend(void)
290 {
291 }
292 
293 //------------------------------------------------------------------------------
294 
295 WinInetBackend* WinInetBackend::createInstance()
296 {
297     return new WinInetBackend;
298 }
299 
300 // ---------------------------------------------------------------------------------------
301 
302 void WinInetBackend::setPropertyValue(
303     rtl::OUString const &, css::uno::Any const &)
304     throw (
305         css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
306         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
307         css::uno::RuntimeException)
308 {
309     throw css::lang::IllegalArgumentException(
310         rtl::OUString(
311             RTL_CONSTASCII_USTRINGPARAM("setPropertyValue not supported")),
312         static_cast< cppu::OWeakObject * >(this), -1);
313 }
314 
315 css::uno::Any WinInetBackend::getPropertyValue(
316     rtl::OUString const & PropertyName)
317     throw (
318         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
319         css::uno::RuntimeException)
320 {
321     if (PropertyName.equalsAsciiL(
322             RTL_CONSTASCII_STRINGPARAM("ooInetFTPProxyName")))
323     {
324         return css::uno::makeAny(valueFtpProxyName_);
325     } else if (PropertyName.equalsAsciiL(
326                    RTL_CONSTASCII_STRINGPARAM("ooInetFTPProxyPort")))
327     {
328         return css::uno::makeAny(valueFtpProxyPort_);
329     } else if (PropertyName.equalsAsciiL(
330                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPProxyName")))
331     {
332         return css::uno::makeAny(valueHttpProxyName_);
333     } else if (PropertyName.equalsAsciiL(
334                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPProxyPort")))
335     {
336         return css::uno::makeAny(valueHttpProxyPort_);
337     } else if (PropertyName.equalsAsciiL(
338                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPSProxyName")))
339     {
340         return css::uno::makeAny(valueHttpsProxyName_);
341     } else if (PropertyName.equalsAsciiL(
342                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPSProxyPort")))
343     {
344         return css::uno::makeAny(valueHttpsProxyPort_);
345     } else if (PropertyName.equalsAsciiL(
346                    RTL_CONSTASCII_STRINGPARAM("ooInetNoProxy")))
347     {
348         return css::uno::makeAny(valueNoProxy_);
349     } else if (PropertyName.equalsAsciiL(
350                    RTL_CONSTASCII_STRINGPARAM("ooInetProxyType")))
351     {
352         return css::uno::makeAny(valueProxyType_);
353     } else {
354         throw css::beans::UnknownPropertyException(
355             PropertyName, static_cast< cppu::OWeakObject * >(this));
356     }
357 }
358 
359 //------------------------------------------------------------------------------
360 
361 rtl::OUString SAL_CALL WinInetBackend::getBackendName(void) {
362 	return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.WinInetBackend") ;
363 }
364 
365 //------------------------------------------------------------------------------
366 
367 rtl::OUString SAL_CALL WinInetBackend::getImplementationName(void)
368     throw (uno::RuntimeException)
369 {
370     return getBackendName() ;
371 }
372 
373 //------------------------------------------------------------------------------
374 
375 uno::Sequence<rtl::OUString> SAL_CALL WinInetBackend::getBackendServiceNames(void)
376 {
377     uno::Sequence<rtl::OUString> aServiceNameList(1);
378     aServiceNameList[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.WinInetBackend")) ;
379 
380     return aServiceNameList ;
381 }
382 
383 //------------------------------------------------------------------------------
384 
385 sal_Bool SAL_CALL WinInetBackend::supportsService(const rtl::OUString& aServiceName)
386     throw (uno::RuntimeException)
387 {
388     uno::Sequence< rtl::OUString > const svc = getBackendServiceNames();
389 
390     for(sal_Int32 i = 0; i < svc.getLength(); ++i )
391         if(svc[i] == aServiceName)
392             return true;
393 
394     return false;
395 }
396 
397 //------------------------------------------------------------------------------
398 
399 uno::Sequence<rtl::OUString> SAL_CALL WinInetBackend::getSupportedServiceNames(void)
400     throw (uno::RuntimeException)
401 {
402     return getBackendServiceNames() ;
403 }
404