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