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