165 lines
5.1 KiB
C++
165 lines
5.1 KiB
C++
|
/*****************************************************************************\
|
||
|
FILE: proxycache.cpp
|
||
|
|
||
|
DESCRIPTION:
|
||
|
FTP Folder uses WININET which doesn't work thru CERN proxies. In that
|
||
|
case, we need to hand control of the FTP URL back to the browser to do the
|
||
|
old URLMON handling of it. The problem is that testing for a CERN proxy
|
||
|
blocking access is expensive.
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
#define PROXY_CACHE_SIZE 15
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
TCHAR szServerName[INTERNET_MAX_HOST_NAME_LENGTH];
|
||
|
BOOL fIsBlocking;
|
||
|
} PROXYCACHEENTRY;
|
||
|
|
||
|
static int g_nLastIndex = 0;
|
||
|
static BOOL g_fInited = FALSE;
|
||
|
static TCHAR g_szProxyServer[MAX_URL_STRING] = {0};
|
||
|
static PROXYCACHEENTRY g_ProxyCache[PROXY_CACHE_SIZE];
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
/////// Private helpers /////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void ProxyCache_Init(void)
|
||
|
{
|
||
|
g_nLastIndex = 0;
|
||
|
|
||
|
for (int nIndex = 0; nIndex < ARRAYSIZE(g_ProxyCache); nIndex++)
|
||
|
{
|
||
|
g_ProxyCache[nIndex].fIsBlocking = FALSE;
|
||
|
g_ProxyCache[nIndex].szServerName[0] = 0;
|
||
|
}
|
||
|
|
||
|
g_fInited = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************\
|
||
|
FUNCTION: ProxyCache_WasProxyChanged
|
||
|
|
||
|
DESCRIPTION:
|
||
|
See if someone changed the proxy settings via
|
||
|
the inetcpl. This is important because it is
|
||
|
frustration to find FTP fails because of the proxy
|
||
|
settings, fix the proxy settings, and then it still
|
||
|
doesn't work because we cached the results.
|
||
|
\****************************************************/
|
||
|
BOOL ProxyCache_WasProxyChanged(void)
|
||
|
{
|
||
|
BOOL fWasChanged = FALSE;
|
||
|
TCHAR szCurrProxyServer[MAX_URL_STRING];
|
||
|
DWORD cbSize = SIZEOF(szCurrProxyServer);
|
||
|
|
||
|
// PERF: If I wanted to be really fast, I would cache the hkey
|
||
|
// so this would be faster. But since my DLL can be loaded/unloaded
|
||
|
// serveral times in a process, I would leak each instance unless I
|
||
|
// released the hkey in DLL_PROCESS_DETACH
|
||
|
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_SETTINGS_LAN, SZ_REGVALUE_PROXY_SERVER, NULL, szCurrProxyServer, &cbSize))
|
||
|
{
|
||
|
// Is this the first time? (Is g_szProxyServer empty?)
|
||
|
if (!g_szProxyServer[0])
|
||
|
StrCpyN(g_szProxyServer, szCurrProxyServer, ARRAYSIZE(g_szProxyServer));
|
||
|
|
||
|
// Did it change?
|
||
|
if (StrCmp(szCurrProxyServer, g_szProxyServer))
|
||
|
fWasChanged = TRUE;
|
||
|
}
|
||
|
|
||
|
return fWasChanged;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
/////// APIs helpers /////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
/****************************************************\
|
||
|
FUNCTION: ProxyCache_IsProxyBlocking
|
||
|
|
||
|
DESCRIPTION:
|
||
|
Look in the cache with the FTP server in pidl
|
||
|
and see if we have a cached value that indicates
|
||
|
if it's blocked by the proxy.
|
||
|
|
||
|
PARAMETERS:
|
||
|
*pfIsBlocking - Is the proxy blocking.
|
||
|
return - Is the value cached
|
||
|
\****************************************************/
|
||
|
BOOL ProxyCache_IsProxyBlocking(LPCITEMIDLIST pidl, BOOL * pfIsBlocking)
|
||
|
{
|
||
|
BOOL fIsInCache = FALSE;
|
||
|
|
||
|
if (ProxyCache_WasProxyChanged())
|
||
|
ProxyCache_Init(); // Purge the results
|
||
|
|
||
|
*pfIsBlocking = FALSE; // Assume we don't know.
|
||
|
if (!g_fInited)
|
||
|
{
|
||
|
ProxyCache_Init();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int nCount = ARRAYSIZE(g_ProxyCache);
|
||
|
TCHAR szNewServer[INTERNET_MAX_HOST_NAME_LENGTH];
|
||
|
|
||
|
// Is this the same server we tried last time? If so,
|
||
|
// let's just cache the return value.
|
||
|
FtpPidl_GetServer(pidl, szNewServer, ARRAYSIZE(szNewServer));
|
||
|
for (int nIndex = g_nLastIndex; nCount && g_ProxyCache[nIndex].szServerName[0]; nCount--, nIndex--)
|
||
|
{
|
||
|
if (nIndex < 0)
|
||
|
nIndex = (PROXY_CACHE_SIZE - 1);
|
||
|
|
||
|
if (!StrCmp(szNewServer, g_ProxyCache[nIndex].szServerName))
|
||
|
{
|
||
|
// Yes, so bail.
|
||
|
*pfIsBlocking = g_ProxyCache[nIndex].fIsBlocking;
|
||
|
fIsInCache = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fIsInCache;
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************\
|
||
|
FUNCTION: ProxyCache_SetProxyBlocking
|
||
|
|
||
|
DESCRIPTION:
|
||
|
|
||
|
PARAMETERS:
|
||
|
*pfIsBlocking - Is the proxy blocking.
|
||
|
return - Is the value cached
|
||
|
\****************************************************/
|
||
|
void ProxyCache_SetProxyBlocking(LPCITEMIDLIST pidl, BOOL fIsBlocking)
|
||
|
{
|
||
|
TCHAR szNewServer[INTERNET_MAX_HOST_NAME_LENGTH];
|
||
|
|
||
|
// Add it to the cache because our caller will hit the server to
|
||
|
// verify and we can be ready for next time.
|
||
|
g_nLastIndex++;
|
||
|
if (g_nLastIndex >= PROXY_CACHE_SIZE)
|
||
|
g_nLastIndex = 0;
|
||
|
|
||
|
FtpPidl_GetServer(pidl, szNewServer, ARRAYSIZE(szNewServer));
|
||
|
StrCpyN(g_ProxyCache[g_nLastIndex].szServerName, szNewServer, ARRAYSIZE(g_ProxyCache[g_nLastIndex].szServerName));
|
||
|
g_ProxyCache[g_nLastIndex].fIsBlocking = fIsBlocking;
|
||
|
}
|