WebParser: Modified proxy handling

- Added new proxy setting switch: /auto, /none
 /auto: use IE setting
 /none: direct connection

Example:
 ProxyServer=/none

- Added global proxy setting. If proxy setting is defined in Rainmeter.data, use it as a global proxy. Default value is /auto.

Example:
 [WebParser.dll]
 ProxyServer=example.net:8080

If ProxyServer= is not defined or is empty string in WebParser measure, use a global proxy. If an individual proxy setting is defined in WebParser measure, use it instead of a global proxy.
This commit is contained in:
spx 2013-01-23 22:04:32 +09:00
parent 7e958bdc23
commit 82eb3ed03f
2 changed files with 223 additions and 26 deletions

View File

@ -7,7 +7,7 @@
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,13,0,0 FILEVERSION 1,14,0,0
PRODUCTVERSION PRODUCTVER PRODUCTVERSION PRODUCTVER
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
@ -23,7 +23,7 @@ VS_VERSION_INFO VERSIONINFO
{ {
BLOCK "040904E4" BLOCK "040904E4"
{ {
VALUE "FileVersion", "1.13.0.0" VALUE "FileVersion", "1.14.0.0"
VALUE "LegalCopyright", "© 2010 - Rainy" VALUE "LegalCopyright", "© 2010 - Rainy"
VALUE "ProductName", "Rainmeter" VALUE "ProductName", "Rainmeter"
#ifdef _WIN64 #ifdef _WIN64

View File

@ -29,6 +29,175 @@
#include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point #include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point
#include "../API/RainmeterAPI.h" #include "../API/RainmeterAPI.h"
void ShowError(int lineNumber, WCHAR* errorMsg = NULL);
class ProxyCachePool
{
public:
ProxyCachePool(LPCWSTR globalProxyName = NULL) :
m_GlobalProxyName((globalProxyName && *globalProxyName) ? globalProxyName : L"/auto")
{
m_GlobalProxyCache = new ProxyCache(CreateProxy(m_GlobalProxyName.c_str()), true);
_wcslwr(&m_GlobalProxyName[0]);
m_CacheMap[m_GlobalProxyName] = m_GlobalProxyCache;
//DebugLog(L"* ADD-GLOBAL: key=%s, handle=0x%p, ref=new", m_GlobalProxyName.c_str(), m_GlobalProxyCache->GetCache());
}
~ProxyCachePool()
{
for (auto iter = m_CacheMap.begin(); iter != m_CacheMap.end(); ++iter)
{
ProxyCache* cache = (*iter).second;
//DebugLog(L"* FORCE-REMOVE: key=%s, global=%i, ref=%i", (*iter).first.c_str(), cache->IsGlobal(), cache->GetRef());
delete cache;
}
}
HINTERNET GetCache(const std::wstring& proxyName)
{
ProxyCache* cache = NULL;
if (proxyName.empty())
{
// Use global proxy setting
cache = m_GlobalProxyCache;
}
else
{
std::wstring key = proxyName;
_wcslwr(&key[0]);
auto iter = m_CacheMap.find(key);
if (iter != m_CacheMap.end())
{
cache = (*iter).second;
}
else // cache not found
{
// Create new proxy
ProxyCache* cache = new ProxyCache(CreateProxy(proxyName.c_str()));
m_CacheMap[key] = cache;
//DebugLog(L"* ADD: key=%s, handle=0x%p, ref=new", key.c_str(), cache->GetCache());
return cache->GetCache();
}
}
// Use proxy cache
cache->AddRef();
//DebugLog(L"* ADD-REF: key=%s, handle=0x%p, global=%i, ref=%i",
// cache->IsGlobal() ? m_GlobalProxyName.c_str() : proxyName.c_str(), cache->GetCache(), cache->IsGlobal(), cache->GetRef());
return cache->GetCache();
}
void RemoveCache(const std::wstring& proxyName)
{
std::wstring key = proxyName.empty() ? m_GlobalProxyName : proxyName;
if (!proxyName.empty())
{
_wcslwr(&key[0]);
}
auto iter = m_CacheMap.find(key);
if (iter != m_CacheMap.end())
{
ProxyCache* cache = (*iter).second;
cache->Release();
//DebugLog(L"* REMOVE: key=%s, global=%i, ref=%i", key.c_str(), cache->IsGlobal(), cache->GetRef());
if (cache->IsInvalid())
{
//DebugLog(L"* EMPTY-ERASE: key=%s", key.c_str());
m_CacheMap.erase(iter);
delete cache;
}
}
}
private:
HINTERNET CreateProxy(LPCWSTR proxyName)
{
DWORD proxyType;
LPCWSTR proxyServer;
if (_wcsicmp(proxyName, L"/auto") == 0)
{
proxyType = INTERNET_OPEN_TYPE_PRECONFIG;
proxyServer = NULL;
}
else if (_wcsicmp(proxyName, L"/none") == 0)
{
proxyType = INTERNET_OPEN_TYPE_DIRECT;
proxyServer = NULL;
}
else
{
proxyType = INTERNET_OPEN_TYPE_PROXY;
proxyServer = proxyName;
}
HINTERNET handle = InternetOpen(L"Rainmeter WebParser plugin",
proxyType,
proxyServer,
NULL,
0);
if (handle)
{
WCHAR buffer[256];
_snwprintf_s(buffer, _TRUNCATE, L"WebParser: ProxyServer=\"%s\" (type=%s, handle=0x%p)",
proxyName,
proxyType == INTERNET_OPEN_TYPE_PRECONFIG ? L"PRECONFIG" : proxyType == INTERNET_OPEN_TYPE_DIRECT ? L"DIRECT" : L"PROXY",
handle);
RmLog(LOG_DEBUG, buffer);
}
else
{
ShowError(__LINE__);
}
return handle;
}
class ProxyCache
{
public:
ProxyCache(HINTERNET handle, bool isGlobal = false) : m_Handle(handle), m_IsGlobal(isGlobal), m_Ref(1) {}
~ProxyCache() { Dispose(); }
void AddRef() { if (!IsInvalid()) { ++m_Ref; } }
void Release() { if (m_Ref > 0) { --m_Ref; } if (IsInvalid()) { Dispose(); } }
bool IsGlobal() { return m_IsGlobal; }
bool IsInvalid() { return (m_Ref <= 0 && !IsGlobal()); }
//int GetRef() { return m_Ref; }
HINTERNET GetCache() { return m_Handle; }
private:
ProxyCache() {}
ProxyCache(const ProxyCache& cache) {}
void Dispose() { if (m_Handle) { InternetCloseHandle(m_Handle); m_Handle = NULL; } }
HINTERNET m_Handle;
bool m_IsGlobal;
int m_Ref;
};
std::unordered_map<std::wstring, ProxyCache*> m_CacheMap;
ProxyCache* m_GlobalProxyCache;
std::wstring m_GlobalProxyName;
};
struct ProxySetting
{
std::wstring server;
HINTERNET handle;
ProxySetting() : handle() {}
};
struct MeasureData struct MeasureData
{ {
std::wstring url; std::wstring url;
@ -42,6 +211,7 @@ struct MeasureData
std::wstring debugFileLocation; std::wstring debugFileLocation;
LPCWSTR section; LPCWSTR section;
void* skin; void* skin;
ProxySetting proxy;
HANDLE threadHandle; HANDLE threadHandle;
HANDLE dlThreadHandle; HANDLE dlThreadHandle;
int codepage; int codepage;
@ -71,18 +241,17 @@ struct MeasureData
} }
}; };
BYTE* DownloadUrl(std::wstring& url, DWORD* dwSize, bool forceReload); BYTE* DownloadUrl(HINTERNET handle, std::wstring& url, DWORD* dwSize, bool forceReload);
void ShowError(int lineNumber, WCHAR* errorMsg = NULL);
unsigned __stdcall NetworkThreadProc(void* pParam); unsigned __stdcall NetworkThreadProc(void* pParam);
unsigned __stdcall NetworkDownloadThreadProc(void* pParam); unsigned __stdcall NetworkDownloadThreadProc(void* pParam);
void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize); void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize);
CRITICAL_SECTION g_CriticalSection; CRITICAL_SECTION g_CriticalSection;
ProxyCachePool* g_ProxyCachePool = NULL;
UINT g_InstanceCount = 0; UINT g_InstanceCount = 0;
static std::vector<MeasureData*> g_Measures; static std::vector<MeasureData*> g_Measures;
static bool g_Debug = false; static bool g_Debug = false;
static HINTERNET g_InternetHandle = NULL;
static std::unordered_map<std::wstring, WCHAR> g_CERs; static std::unordered_map<std::wstring, WCHAR> g_CERs;
@ -535,6 +704,44 @@ void FillCharacterEntityReferences()
//} //}
} }
void SetupGlobalProxySetting()
{
if (!g_ProxyCachePool)
{
WCHAR buffer[MAX_PATH] = {0};
LPCWSTR file = RmGetSettingsFile();
GetPrivateProfileString(L"WebParser.dll", L"ProxyServer", NULL, buffer, MAX_PATH, file);
g_ProxyCachePool = new ProxyCachePool(buffer);
}
}
void ClearGlobalProxySetting()
{
delete g_ProxyCachePool;
g_ProxyCachePool = NULL;
}
void SetupProxySetting(ProxySetting& setting, void* rm)
{
if (g_ProxyCachePool)
{
setting.server = RmReadString(rm, L"ProxyServer", L"");
setting.handle = g_ProxyCachePool->GetCache(setting.server);
}
}
void ClearProxySetting(ProxySetting& setting)
{
if (g_ProxyCachePool)
{
g_ProxyCachePool->RemoveCache(setting.server);
}
setting.handle = NULL;
setting.server.clear();
}
PLUGIN_EXPORT void Initialize(void** data, void* rm) PLUGIN_EXPORT void Initialize(void** data, void* rm)
{ {
MeasureData* measure = new MeasureData; MeasureData* measure = new MeasureData;
@ -548,19 +755,11 @@ PLUGIN_EXPORT void Initialize(void** data, void* rm)
InitializeCriticalSection(&g_CriticalSection); InitializeCriticalSection(&g_CriticalSection);
FillCharacterEntityReferences(); FillCharacterEntityReferences();
LPCWSTR proxy = RmReadString(rm, L"ProxyServer", L""); SetupGlobalProxySetting();
g_InternetHandle = InternetOpen(L"Rainmeter WebParser plugin",
*proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
*proxy ? proxy : NULL,
NULL,
0);
if (g_InternetHandle == NULL)
{
ShowError(__LINE__);
}
} }
SetupProxySetting(measure->proxy, rm); // No support for DynamicVariables
++g_InstanceCount; ++g_InstanceCount;
} }
@ -699,7 +898,7 @@ unsigned __stdcall NetworkThreadProc(void* pParam)
MeasureData* measure = (MeasureData*)pParam; MeasureData* measure = (MeasureData*)pParam;
DWORD dwSize = 0; DWORD dwSize = 0;
BYTE* data = DownloadUrl(measure->url, &dwSize, measure->forceReload); BYTE* data = DownloadUrl(measure->proxy.handle, measure->url, &dwSize, measure->forceReload);
if (data) if (data)
{ {
@ -1433,6 +1632,8 @@ PLUGIN_EXPORT void Finalize(void* data)
} }
} }
ClearProxySetting(measure->proxy);
delete measure; delete measure;
std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure);
g_Measures.erase(iter); g_Measures.erase(iter);
@ -1441,11 +1642,7 @@ PLUGIN_EXPORT void Finalize(void* data)
if (g_InstanceCount == 0) if (g_InstanceCount == 0)
{ {
// Last one, close all handles // Last one, close all handles
if (g_InternetHandle) ClearGlobalProxySetting();
{
InternetCloseHandle(g_InternetHandle);
g_InternetHandle = NULL;
}
g_CERs.clear(); g_CERs.clear();
@ -1458,7 +1655,7 @@ PLUGIN_EXPORT void Finalize(void* data)
Downloads the given url and returns the webpage as dynamically allocated string. Downloads the given url and returns the webpage as dynamically allocated string.
You need to delete the returned string after use! You need to delete the returned string after use!
*/ */
BYTE* DownloadUrl(std::wstring& url, DWORD* dwDataSize, bool forceReload) BYTE* DownloadUrl(HINTERNET handle, std::wstring& url, DWORD* dwDataSize, bool forceReload)
{ {
HINTERNET hUrlDump; HINTERNET hUrlDump;
DWORD dwSize; DWORD dwSize;
@ -1478,13 +1675,13 @@ BYTE* DownloadUrl(std::wstring& url, DWORD* dwDataSize, bool forceReload)
flags = INTERNET_FLAG_RELOAD; flags = INTERNET_FLAG_RELOAD;
} }
hUrlDump = InternetOpenUrl(g_InternetHandle, url.c_str(), NULL, NULL, flags, 0); hUrlDump = InternetOpenUrl(handle, url.c_str(), NULL, NULL, flags, 0);
if (hUrlDump == NULL) if (hUrlDump == NULL)
{ {
if (_wcsnicmp(url.c_str(), L"file://", 7) == 0) // file scheme if (_wcsnicmp(url.c_str(), L"file://", 7) == 0) // file scheme
{ {
std::string urlACP = ConvertWideToAscii(url.c_str()); std::string urlACP = ConvertWideToAscii(url.c_str());
hUrlDump = InternetOpenUrlA(g_InternetHandle, urlACP.c_str(), NULL, NULL, flags, 0); hUrlDump = InternetOpenUrlA(handle, urlACP.c_str(), NULL, NULL, flags, 0);
} }
if (hUrlDump == NULL) if (hUrlDump == NULL)
@ -1647,7 +1844,7 @@ void ShowError(int lineNumber, WCHAR* errorMsg)
UINT GetPluginVersion() UINT GetPluginVersion()
{ {
return 1013; return 1014;
} }
LPCTSTR GetPluginAuthor() LPCTSTR GetPluginAuthor()