bump product version to 6.3.0.0.beta1
[LibreOffice.git] / shell / source / backends / wininetbe / wininetbackend.cxx
blobadc0133dfc32188c67b63770ae889c5bd4e97b12
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <sal/log.hxx>
24 #include "wininetbackend.hxx"
26 #if !defined WIN32_LEAN_AND_MEAN
27 # define WIN32_LEAN_AND_MEAN
28 #endif
29 #include <windows.h>
30 #include <wininet.h>
31 #include <sal/alloca.h>
33 #define WININET_DLL_NAME L"wininet.dll"
34 #define EQUAL_SIGN '='
35 #define COLON ':'
36 #define SPACE ' '
37 #define SEMI_COLON ';'
39 namespace {
41 struct Library {
42 HMODULE module;
44 explicit Library(HMODULE theModule): module(theModule) {}
46 ~Library() { if (module) FreeLibrary(module); }
51 struct ProxyEntry
53 OUString Server;
54 OUString Port;
58 namespace
60 ProxyEntry ReadProxyEntry(const OUString& aProxy, sal_Int32& i)
62 ProxyEntry aProxyEntry;
64 aProxyEntry.Server = aProxy.getToken( 0, COLON, i );
65 if ( i > -1 )
66 aProxyEntry.Port = aProxy.getToken( 0, COLON, i );
68 return aProxyEntry;
71 ProxyEntry FindProxyEntry(const OUString& aProxyList, const OUString& aType)
73 sal_Int32 nIndex = 0;
77 // get the next token, e.g. ftp=server:port
78 OUString nextToken = aProxyList.getToken( 0, SPACE, nIndex );
80 // split the next token again into the parts separated
81 // through '=', e.g. ftp=server:port -> ftp and server:port
82 sal_Int32 i = 0;
83 if( nextToken.indexOf( EQUAL_SIGN ) > -1 )
85 if( aType.equals( nextToken.getToken( 0, EQUAL_SIGN, i ) ) )
86 return ReadProxyEntry(nextToken, i);
88 else if( aType.isEmpty())
89 return ReadProxyEntry(nextToken, i);
91 } while ( nIndex >= 0 );
93 return ProxyEntry();
96 } // unnamed namespace
98 WinInetBackend::WinInetBackend()
100 Library hWinInetDll( LoadLibraryW( WININET_DLL_NAME ) );
101 if( hWinInetDll.module )
103 typedef BOOL ( WINAPI *InternetQueryOption_Proc_T )( HINTERNET, DWORD, LPVOID, LPDWORD );
105 InternetQueryOption_Proc_T lpfnInternetQueryOption =
106 reinterpret_cast< InternetQueryOption_Proc_T >(
107 GetProcAddress( hWinInetDll.module, "InternetQueryOptionW" ) );
108 if (lpfnInternetQueryOption)
110 // Some Windows versions would fail the InternetQueryOption call
111 // with ERROR_OUTOFMEMORY when the initial dwLength were zero (and
112 // are apparently fine with the initial sizeof (INTERNET_PROXY_INFO)
113 // and need no reallocation), while other versions fail with
114 // ERROR_INSUFFICIENT_BUFFER upon that initial dwLength and need a
115 // reallocation:
116 INTERNET_PROXY_INFO pi;
117 LPINTERNET_PROXY_INFO lpi = &pi;
118 DWORD dwLength = sizeof (pi);
119 BOOL ok = lpfnInternetQueryOption(
120 nullptr,
121 INTERNET_OPTION_PROXY,
122 lpi,
123 &dwLength );
124 if (!ok)
126 DWORD err = GetLastError();
127 if (err == ERROR_INSUFFICIENT_BUFFER)
129 // allocate sufficient space on the stack
130 // insufficient space on the stack results
131 // in a stack overflow exception, we assume
132 // this never happens, because of the relatively
133 // small amount of memory we need
134 // alloca is nice because it is fast and we don't
135 // have to free the allocated memory, it will be
136 // automatically done
137 lpi = static_cast< LPINTERNET_PROXY_INFO >(
138 alloca( dwLength ) );
139 ok = lpfnInternetQueryOption(
140 nullptr,
141 INTERNET_OPTION_PROXY,
142 lpi,
143 &dwLength );
144 if (!ok)
146 err = GetLastError();
149 if (!ok)
151 SAL_WARN(
152 "shell",
153 "InternetQueryOption INTERNET_OPTION_PROXY"
154 " GetLastError=" << err);
155 return;
159 // if a proxy is disabled, InternetQueryOption returns
160 // an empty proxy list, so we don't have to check if
161 // proxy is enabled or not
163 // We use InternetQueryOptionW (see https://msdn.microsoft.com/en-us/library/aa385101);
164 // it fills INTERNET_PROXY_INFO struct which is defined in WinInet.h to have LPCTSTR
165 // (i.e., the UNICODE-dependent generic string type expanding to const wchar_t* when
166 // UNICODE is defined, and InternetQueryOption macro expands to InternetQueryOptionW).
167 // Thus, it's natural to expect that W version would return wide strings. But it's not
168 // true. The W version still returns const char* in INTERNET_PROXY_INFO.
169 OUString aProxyList = OUString::createFromAscii( lpi->lpszProxy );
170 OUString aProxyBypassList = OUString::createFromAscii( lpi->lpszProxyBypass );
172 // override default for ProxyType, which is "0" meaning "No proxies".
173 valueProxyType_.IsPresent = true;
174 valueProxyType_.Value <<= sal_Int32(1);
176 // fill proxy bypass list
177 if( aProxyBypassList.getLength() > 0 )
179 OUStringBuffer aReverseList;
180 sal_Int32 nIndex = 0;
183 OUString aToken = aProxyBypassList.getToken( 0, SPACE, nIndex );
184 if ( aProxyList.indexOf( aToken ) == -1 )
186 if ( aReverseList.getLength() )
188 aReverseList.insert( 0, sal_Unicode( SEMI_COLON ) );
189 aReverseList.insert( 0, aToken );
191 else
192 aReverseList = aToken;
195 while ( nIndex >= 0 );
197 aProxyBypassList = aReverseList.makeStringAndClear();
199 valueNoProxy_.IsPresent = true;
200 valueNoProxy_.Value <<= aProxyBypassList.replace( SPACE, SEMI_COLON );
203 if( aProxyList.getLength() > 0 )
206 // this implementation follows the algorithm
207 // of the internet explorer
208 // if there are type-dependent proxy settings
209 // and type independent proxy settings in the
210 // registry the internet explorer chooses the
211 // type independent proxy for all settings
212 // e.g. imagine the following registry entry
213 // ftp=server:port;http=server:port;server:port
214 // the last token server:port is type independent
215 // so the ie chooses this proxy server
217 // if there is no port specified for a type independent
218 // server the ie uses the port of an http server if
219 // there is one and it has a port
222 ProxyEntry aTypeIndepProxy = FindProxyEntry( aProxyList, OUString());
223 ProxyEntry aHttpProxy = FindProxyEntry( aProxyList, "http" );
224 ProxyEntry aHttpsProxy = FindProxyEntry( aProxyList, "https" );
226 ProxyEntry aFtpProxy = FindProxyEntry( aProxyList, "ftp" );
228 if( aTypeIndepProxy.Server.getLength() )
230 aHttpProxy.Server = aTypeIndepProxy.Server;
231 aHttpsProxy.Server = aTypeIndepProxy.Server;
232 aFtpProxy.Server = aTypeIndepProxy.Server;
234 if( aTypeIndepProxy.Port.getLength() )
236 aHttpProxy.Port = aTypeIndepProxy.Port;
237 aHttpsProxy.Port = aTypeIndepProxy.Port;
238 aFtpProxy.Port = aTypeIndepProxy.Port;
240 else
242 aFtpProxy.Port = aHttpProxy.Port;
243 aHttpsProxy.Port = aHttpProxy.Port;
247 // http proxy name
248 if( aHttpProxy.Server.getLength() > 0 )
250 valueHttpProxyName_.IsPresent = true;
251 valueHttpProxyName_.Value <<= aHttpProxy.Server;
254 // http proxy port
255 if( aHttpProxy.Port.getLength() > 0 )
257 valueHttpProxyPort_.IsPresent = true;
258 valueHttpProxyPort_.Value <<= aHttpProxy.Port.toInt32();
261 // https proxy name
262 if( aHttpsProxy.Server.getLength() > 0 )
264 valueHttpsProxyName_.IsPresent = true;
265 valueHttpsProxyName_.Value <<= aHttpsProxy.Server;
268 // https proxy port
269 if( aHttpsProxy.Port.getLength() > 0 )
271 valueHttpsProxyPort_.IsPresent = true;
272 valueHttpsProxyPort_.Value <<= aHttpsProxy.Port.toInt32();
275 // ftp proxy name
276 if( aFtpProxy.Server.getLength() > 0 )
278 valueFtpProxyName_.IsPresent = true;
279 valueFtpProxyName_.Value <<= aFtpProxy.Server;
282 // ftp proxy port
283 if( aFtpProxy.Port.getLength() > 0 )
285 valueFtpProxyPort_.IsPresent = true;
286 valueFtpProxyPort_.Value <<= aFtpProxy.Port.toInt32();
293 WinInetBackend::~WinInetBackend()
297 WinInetBackend* WinInetBackend::createInstance()
299 return new WinInetBackend;
302 void WinInetBackend::setPropertyValue(
303 OUString const &, css::uno::Any const &)
305 throw css::lang::IllegalArgumentException(
306 "setPropertyValue not supported",
307 static_cast< cppu::OWeakObject * >(this), -1);
310 css::uno::Any WinInetBackend::getPropertyValue(
311 OUString const & PropertyName)
313 if ( PropertyName == "ooInetFTPProxyName" )
315 return css::uno::makeAny(valueFtpProxyName_);
316 } else if ( PropertyName == "ooInetFTPProxyPort" )
318 return css::uno::makeAny(valueFtpProxyPort_);
319 } else if ( PropertyName == "ooInetHTTPProxyName" )
321 return css::uno::makeAny(valueHttpProxyName_);
322 } else if ( PropertyName == "ooInetHTTPProxyPort" )
324 return css::uno::makeAny(valueHttpProxyPort_);
325 } else if ( PropertyName == "ooInetHTTPSProxyName" )
327 return css::uno::makeAny(valueHttpsProxyName_);
328 } else if ( PropertyName == "ooInetHTTPSProxyPort" )
330 return css::uno::makeAny(valueHttpsProxyPort_);
331 } else if ( PropertyName == "ooInetNoProxy" )
333 return css::uno::makeAny(valueNoProxy_);
334 } else if ( PropertyName == "ooInetProxyType" )
336 return css::uno::makeAny(valueProxyType_);
337 } else {
338 throw css::beans::UnknownPropertyException(
339 PropertyName, static_cast< cppu::OWeakObject * >(this));
343 OUString WinInetBackend::getBackendName() {
344 return OUString("com.sun.star.comp.configuration.backend.WinInetBackend") ;
347 OUString SAL_CALL WinInetBackend::getImplementationName()
349 return getBackendName() ;
352 uno::Sequence<OUString> WinInetBackend::getBackendServiceNames()
354 uno::Sequence<OUString> aServiceNameList { "com.sun.star.configuration.backend.WinInetBackend" };
356 return aServiceNameList ;
359 sal_Bool SAL_CALL WinInetBackend::supportsService(const OUString& aServiceName)
361 return cppu::supportsService(this, aServiceName);
364 uno::Sequence<OUString> SAL_CALL WinInetBackend::getSupportedServiceNames()
366 return getBackendServiceNames() ;
369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */