2009-02-14 10:11:28 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 2005 Kimmo Pekkola
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2012-01-23 06:36:15 +00:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-02-10 18:37:48 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
#include <string>
|
2012-02-20 09:37:46 +00:00
|
|
|
#include <unordered_map>
|
2009-02-10 18:37:48 +00:00
|
|
|
#include <vector>
|
2012-02-18 18:08:18 +00:00
|
|
|
#include <algorithm>
|
2009-02-10 18:37:48 +00:00
|
|
|
#include <Wininet.h>
|
2010-01-12 21:45:47 +00:00
|
|
|
#include <shlwapi.h>
|
2010-08-31 19:49:47 +00:00
|
|
|
#include <process.h>
|
2011-05-16 09:24:13 +00:00
|
|
|
#include "../../Library/pcre-8.10/config.h"
|
2011-02-03 18:09:24 +00:00
|
|
|
#include "../../Library/pcre-8.10/pcre.h"
|
|
|
|
#include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point
|
2012-02-18 18:08:18 +00:00
|
|
|
#include "../API/RainmeterAPI.h"
|
2011-01-30 09:31:41 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
struct MeasureData
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
std::wstring url;
|
|
|
|
std::wstring regExp;
|
|
|
|
std::wstring resultString;
|
|
|
|
std::wstring errorString;
|
2012-02-18 18:08:18 +00:00
|
|
|
std::wstring finishAction;
|
|
|
|
std::wstring downloadFolder;
|
|
|
|
std::wstring downloadFile;
|
|
|
|
std::wstring downloadedFile;
|
|
|
|
std::wstring debugFileLocation;
|
|
|
|
LPCWSTR section;
|
|
|
|
void* skin;
|
|
|
|
HANDLE threadHandle;
|
|
|
|
HANDLE dlThreadHandle;
|
2009-02-10 18:37:48 +00:00
|
|
|
int codepage;
|
|
|
|
int stringIndex;
|
|
|
|
int stringIndex2;
|
2010-08-31 19:49:47 +00:00
|
|
|
int decodeCharacterReference;
|
2012-02-18 18:08:18 +00:00
|
|
|
int debug;
|
2009-02-10 18:37:48 +00:00
|
|
|
UINT updateRate;
|
|
|
|
UINT updateCounter;
|
|
|
|
bool download;
|
2009-08-19 18:07:56 +00:00
|
|
|
bool forceReload;
|
2009-02-10 18:37:48 +00:00
|
|
|
};
|
|
|
|
|
2009-08-19 18:07:56 +00:00
|
|
|
BYTE* DownloadUrl(std::wstring& url, DWORD* dwSize, bool forceReload);
|
2009-02-10 18:37:48 +00:00
|
|
|
void ShowError(int lineNumber, WCHAR* errorMsg = NULL);
|
2010-08-31 19:49:47 +00:00
|
|
|
unsigned __stdcall NetworkThreadProc(void* pParam);
|
|
|
|
unsigned __stdcall NetworkDownloadThreadProc(void* pParam);
|
2011-08-19 13:33:49 +00:00
|
|
|
void Log(int level, const WCHAR* string);
|
2012-02-18 18:08:18 +00:00
|
|
|
void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
CRITICAL_SECTION g_CriticalSection;
|
2012-02-18 18:08:18 +00:00
|
|
|
UINT g_InstanceCount = 0;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
static std::vector<MeasureData*> g_Measures;
|
2009-02-10 18:37:48 +00:00
|
|
|
static bool g_Debug = false;
|
2012-02-18 18:08:18 +00:00
|
|
|
static HINTERNET g_InternetHandle = NULL;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-20 09:37:46 +00:00
|
|
|
static std::unordered_map<std::wstring, WCHAR> g_CERs;
|
2010-08-31 19:49:47 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
#define OVECCOUNT 300 // should be a multiple of 3
|
|
|
|
|
2010-08-19 09:24:25 +00:00
|
|
|
std::wstring ConvertToWide(LPCSTR str, int codepage)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-08-19 09:24:25 +00:00
|
|
|
std::wstring szWide;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-09-12 11:11:40 +00:00
|
|
|
if (str && *str)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2011-10-10 08:20:31 +00:00
|
|
|
int strLen = (int)strlen(str);
|
2009-09-12 11:11:40 +00:00
|
|
|
int bufLen = MultiByteToWideChar(codepage, 0, str, strLen, NULL, 0);
|
|
|
|
if (bufLen > 0)
|
|
|
|
{
|
2011-10-10 08:20:31 +00:00
|
|
|
szWide.resize(bufLen);
|
|
|
|
MultiByteToWideChar(codepage, 0, str, strLen, &szWide[0], bufLen);
|
2009-09-12 11:11:40 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
return szWide;
|
|
|
|
}
|
|
|
|
|
2010-08-19 09:24:25 +00:00
|
|
|
std::string ConvertToAscii(LPCWSTR str, int codepage)
|
2010-02-03 08:01:50 +00:00
|
|
|
{
|
|
|
|
std::string szAscii;
|
|
|
|
|
|
|
|
if (str && *str)
|
|
|
|
{
|
2011-10-10 08:20:31 +00:00
|
|
|
int strLen = (int)wcslen(str);
|
2010-08-19 09:24:25 +00:00
|
|
|
int bufLen = WideCharToMultiByte(codepage, 0, str, strLen, NULL, 0, NULL, NULL);
|
2010-02-03 08:01:50 +00:00
|
|
|
if (bufLen > 0)
|
|
|
|
{
|
2011-10-10 08:20:31 +00:00
|
|
|
szAscii.resize(bufLen);
|
|
|
|
WideCharToMultiByte(codepage, 0, str, strLen, &szAscii[0], bufLen, NULL, NULL);
|
2010-02-03 08:01:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return szAscii;
|
|
|
|
}
|
|
|
|
|
2010-08-19 09:24:25 +00:00
|
|
|
std::string ConvertWideToAscii(LPCWSTR str)
|
|
|
|
{
|
|
|
|
return ConvertToAscii(str, CP_ACP);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring ConvertAsciiToWide(LPCSTR str)
|
|
|
|
{
|
|
|
|
return ConvertToWide(str, CP_ACP);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring ConvertUTF8ToWide(LPCSTR str)
|
|
|
|
{
|
|
|
|
return ConvertToWide(str, CP_UTF8);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string ConvertWideToUTF8(LPCWSTR str)
|
|
|
|
{
|
|
|
|
return ConvertToAscii(str, CP_UTF8);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string ConvertAsciiToUTF8(LPCSTR str, int codepage)
|
|
|
|
{
|
|
|
|
std::string szUTF8;
|
|
|
|
|
|
|
|
if (str && *str)
|
|
|
|
{
|
|
|
|
std::wstring wide = ConvertToWide(str, codepage);
|
|
|
|
if (!wide.empty())
|
|
|
|
{
|
|
|
|
szUTF8.swap(ConvertWideToUTF8(wide.c_str()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return szUTF8;
|
|
|
|
}
|
|
|
|
|
2010-08-31 19:49:47 +00:00
|
|
|
std::wstring& DecodeReferences(std::wstring& str, int opt)
|
|
|
|
{
|
|
|
|
// (opt <= 0 || opt > 3) : Do nothing.
|
|
|
|
// (opt == 1) : Decode both numeric character references and character entity references.
|
|
|
|
// (opt == 2) : Decode only numeric character references.
|
|
|
|
// (opt == 3) : Decode only character entity references.
|
|
|
|
|
|
|
|
if (opt >= 1 && opt <= 3)
|
|
|
|
{
|
|
|
|
std::wstring::size_type start = 0;
|
|
|
|
|
|
|
|
while ((start = str.find(L'&', start)) != std::wstring::npos)
|
|
|
|
{
|
|
|
|
std::wstring::size_type end, pos;
|
|
|
|
|
|
|
|
if ((end = str.find(L';', start)) == std::wstring::npos) break;
|
|
|
|
pos = start + 1;
|
|
|
|
|
|
|
|
if (pos == end) // &; - skip
|
|
|
|
{
|
|
|
|
start = end + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ((end - pos) > 10) // name (or number) is too long
|
|
|
|
{
|
|
|
|
++start;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str[pos] == L'#') // Numeric character reference
|
|
|
|
{
|
|
|
|
if (opt == 3 || // Decode only character entity references,
|
|
|
|
++pos == end) // &#; - skip
|
|
|
|
{
|
|
|
|
start = end + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int base;
|
|
|
|
if (str[pos] == L'x' || str[pos] == L'X')
|
|
|
|
{
|
|
|
|
if (++pos == end) // &#x; or &#X; - skip
|
|
|
|
{
|
|
|
|
start = end + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
base = 16;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base = 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring num(str, pos, end - pos);
|
|
|
|
WCHAR* pch = NULL;
|
|
|
|
errno = 0;
|
|
|
|
long ch = wcstol(num.c_str(), &pch, base);
|
|
|
|
if (pch == NULL || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch >= 0xFFFE) // invalid character
|
|
|
|
{
|
|
|
|
start = pos;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
str.replace(start, end - start + 1, 1, (WCHAR)ch);
|
|
|
|
++start;
|
|
|
|
}
|
|
|
|
else // Character entity reference
|
|
|
|
{
|
|
|
|
if (opt == 2) // Decode only numeric character references - skip
|
|
|
|
{
|
|
|
|
start = end + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring name(str, pos, end - pos);
|
|
|
|
|
2012-02-20 09:37:46 +00:00
|
|
|
std::unordered_map<std::wstring, WCHAR>::const_iterator iter = g_CERs.find(name);
|
2010-08-31 19:49:47 +00:00
|
|
|
if (iter != g_CERs.end())
|
|
|
|
{
|
|
|
|
str.replace(start, end - start + 1, 1, (*iter).second);
|
|
|
|
}
|
|
|
|
++start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FillCharacterEntityReferences()
|
|
|
|
{
|
2012-02-18 16:02:10 +00:00
|
|
|
struct CER
|
|
|
|
{
|
|
|
|
WCHAR* name;
|
|
|
|
WCHAR ch;
|
|
|
|
};
|
|
|
|
|
2010-09-09 09:59:30 +00:00
|
|
|
// List from:
|
|
|
|
// http://www.w3.org/TR/html4/sgml/entities.html
|
|
|
|
// http://www.w3.org/TR/xhtml1/#C_16
|
2012-02-18 16:02:10 +00:00
|
|
|
static CER entities[] =
|
|
|
|
{
|
|
|
|
// for markup-significant and internationalization characters
|
|
|
|
{ L"quot", (WCHAR)34 },
|
|
|
|
{ L"amp", (WCHAR)38 },
|
|
|
|
{ L"apos", (WCHAR)39 },
|
|
|
|
{ L"lt", (WCHAR)60 },
|
|
|
|
{ L"gt", (WCHAR)62 },
|
|
|
|
{ L"OElig", (WCHAR)338 },
|
|
|
|
{ L"oelig", (WCHAR)339 },
|
|
|
|
{ L"Scaron", (WCHAR)352 },
|
|
|
|
{ L"scaron", (WCHAR)353 },
|
|
|
|
{ L"Yuml", (WCHAR)376 },
|
|
|
|
{ L"circ", (WCHAR)710 },
|
|
|
|
{ L"tilde", (WCHAR)732 },
|
|
|
|
{ L"ensp", (WCHAR)8194 },
|
|
|
|
{ L"emsp", (WCHAR)8195 },
|
|
|
|
{ L"thinsp", (WCHAR)8201 },
|
|
|
|
{ L"zwnj", (WCHAR)8204 },
|
|
|
|
{ L"zwj", (WCHAR)8205 },
|
|
|
|
{ L"lrm", (WCHAR)8206 },
|
|
|
|
{ L"rlm", (WCHAR)8207 },
|
|
|
|
{ L"ndash", (WCHAR)8211 },
|
|
|
|
{ L"mdash", (WCHAR)8212 },
|
|
|
|
{ L"lsquo", (WCHAR)8216 },
|
|
|
|
{ L"rsquo", (WCHAR)8217 },
|
|
|
|
{ L"sbquo", (WCHAR)8218 },
|
|
|
|
{ L"ldquo", (WCHAR)8220 },
|
|
|
|
{ L"rdquo", (WCHAR)8221 },
|
|
|
|
{ L"bdquo", (WCHAR)8222 },
|
|
|
|
{ L"dagger", (WCHAR)8224 },
|
|
|
|
{ L"Dagger", (WCHAR)8225 },
|
|
|
|
{ L"permil", (WCHAR)8240 },
|
|
|
|
{ L"lsaquo", (WCHAR)8249 },
|
|
|
|
{ L"rsaquo", (WCHAR)8250 },
|
|
|
|
{ L"euro", (WCHAR)8364 },
|
|
|
|
|
|
|
|
// for ISO 8859-1 characters
|
|
|
|
{ L"nbsp", (WCHAR)160 },
|
|
|
|
{ L"iexcl", (WCHAR)161 },
|
|
|
|
{ L"cent", (WCHAR)162 },
|
|
|
|
{ L"pound", (WCHAR)163 },
|
|
|
|
{ L"curren", (WCHAR)164 },
|
|
|
|
{ L"yen", (WCHAR)165 },
|
|
|
|
{ L"brvbar", (WCHAR)166 },
|
|
|
|
{ L"sect", (WCHAR)167 },
|
|
|
|
{ L"uml", (WCHAR)168 },
|
|
|
|
{ L"copy", (WCHAR)169 },
|
|
|
|
{ L"ordf", (WCHAR)170 },
|
|
|
|
{ L"laquo", (WCHAR)171 },
|
|
|
|
{ L"not", (WCHAR)172 },
|
|
|
|
{ L"shy", (WCHAR)173 },
|
|
|
|
{ L"reg", (WCHAR)174 },
|
|
|
|
{ L"macr", (WCHAR)175 },
|
|
|
|
{ L"deg", (WCHAR)176 },
|
|
|
|
{ L"plusmn", (WCHAR)177 },
|
|
|
|
{ L"sup2", (WCHAR)178 },
|
|
|
|
{ L"sup3", (WCHAR)179 },
|
|
|
|
{ L"acute", (WCHAR)180 },
|
|
|
|
{ L"micro", (WCHAR)181 },
|
|
|
|
{ L"para", (WCHAR)182 },
|
|
|
|
{ L"middot", (WCHAR)183 },
|
|
|
|
{ L"cedil", (WCHAR)184 },
|
|
|
|
{ L"sup1", (WCHAR)185 },
|
|
|
|
{ L"ordm", (WCHAR)186 },
|
|
|
|
{ L"raquo", (WCHAR)187 },
|
|
|
|
{ L"frac14", (WCHAR)188 },
|
|
|
|
{ L"frac12", (WCHAR)189 },
|
|
|
|
{ L"frac34", (WCHAR)190 },
|
|
|
|
{ L"iquest", (WCHAR)191 },
|
|
|
|
{ L"Agrave", (WCHAR)192 },
|
|
|
|
{ L"Aacute", (WCHAR)193 },
|
|
|
|
{ L"Acirc", (WCHAR)194 },
|
|
|
|
{ L"Atilde", (WCHAR)195 },
|
|
|
|
{ L"Auml", (WCHAR)196 },
|
|
|
|
{ L"Aring", (WCHAR)197 },
|
|
|
|
{ L"AElig", (WCHAR)198 },
|
|
|
|
{ L"Ccedil", (WCHAR)199 },
|
|
|
|
{ L"Egrave", (WCHAR)200 },
|
|
|
|
{ L"Eacute", (WCHAR)201 },
|
|
|
|
{ L"Ecirc", (WCHAR)202 },
|
|
|
|
{ L"Euml", (WCHAR)203 },
|
|
|
|
{ L"Igrave", (WCHAR)204 },
|
|
|
|
{ L"Iacute", (WCHAR)205 },
|
|
|
|
{ L"Icirc", (WCHAR)206 },
|
|
|
|
{ L"Iuml", (WCHAR)207 },
|
|
|
|
{ L"ETH", (WCHAR)208 },
|
|
|
|
{ L"Ntilde", (WCHAR)209 },
|
|
|
|
{ L"Ograve", (WCHAR)210 },
|
|
|
|
{ L"Oacute", (WCHAR)211 },
|
|
|
|
{ L"Ocirc", (WCHAR)212 },
|
|
|
|
{ L"Otilde", (WCHAR)213 },
|
|
|
|
{ L"Ouml", (WCHAR)214 },
|
|
|
|
{ L"times", (WCHAR)215 },
|
|
|
|
{ L"Oslash", (WCHAR)216 },
|
|
|
|
{ L"Ugrave", (WCHAR)217 },
|
|
|
|
{ L"Uacute", (WCHAR)218 },
|
|
|
|
{ L"Ucirc", (WCHAR)219 },
|
|
|
|
{ L"Uuml", (WCHAR)220 },
|
|
|
|
{ L"Yacute", (WCHAR)221 },
|
|
|
|
{ L"THORN", (WCHAR)222 },
|
|
|
|
{ L"szlig", (WCHAR)223 },
|
|
|
|
{ L"agrave", (WCHAR)224 },
|
|
|
|
{ L"aacute", (WCHAR)225 },
|
|
|
|
{ L"acirc", (WCHAR)226 },
|
|
|
|
{ L"atilde", (WCHAR)227 },
|
|
|
|
{ L"auml", (WCHAR)228 },
|
|
|
|
{ L"aring", (WCHAR)229 },
|
|
|
|
{ L"aelig", (WCHAR)230 },
|
|
|
|
{ L"ccedil", (WCHAR)231 },
|
|
|
|
{ L"egrave", (WCHAR)232 },
|
|
|
|
{ L"eacute", (WCHAR)233 },
|
|
|
|
{ L"ecirc", (WCHAR)234 },
|
|
|
|
{ L"euml", (WCHAR)235 },
|
|
|
|
{ L"igrave", (WCHAR)236 },
|
|
|
|
{ L"iacute", (WCHAR)237 },
|
|
|
|
{ L"icirc", (WCHAR)238 },
|
|
|
|
{ L"iuml", (WCHAR)239 },
|
|
|
|
{ L"eth", (WCHAR)240 },
|
|
|
|
{ L"ntilde", (WCHAR)241 },
|
|
|
|
{ L"ograve", (WCHAR)242 },
|
|
|
|
{ L"oacute", (WCHAR)243 },
|
|
|
|
{ L"ocirc", (WCHAR)244 },
|
|
|
|
{ L"otilde", (WCHAR)245 },
|
|
|
|
{ L"ouml", (WCHAR)246 },
|
|
|
|
{ L"divide", (WCHAR)247 },
|
|
|
|
{ L"oslash", (WCHAR)248 },
|
|
|
|
{ L"ugrave", (WCHAR)249 },
|
|
|
|
{ L"uacute", (WCHAR)250 },
|
|
|
|
{ L"ucirc", (WCHAR)251 },
|
|
|
|
{ L"uuml", (WCHAR)252 },
|
|
|
|
{ L"yacute", (WCHAR)253 },
|
|
|
|
{ L"thorn", (WCHAR)254 },
|
|
|
|
{ L"yuml", (WCHAR)255 },
|
|
|
|
|
|
|
|
// for symbols, mathematical symbols, and Greek letters
|
|
|
|
{ L"fnof", (WCHAR)402 },
|
|
|
|
{ L"Alpha", (WCHAR)913 },
|
|
|
|
{ L"Beta", (WCHAR)914 },
|
|
|
|
{ L"Gamma", (WCHAR)915 },
|
|
|
|
{ L"Delta", (WCHAR)916 },
|
|
|
|
{ L"Epsilon", (WCHAR)917 },
|
|
|
|
{ L"Zeta", (WCHAR)918 },
|
|
|
|
{ L"Eta", (WCHAR)919 },
|
|
|
|
{ L"Theta", (WCHAR)920 },
|
|
|
|
{ L"Iota", (WCHAR)921 },
|
|
|
|
{ L"Kappa", (WCHAR)922 },
|
|
|
|
{ L"Lambda", (WCHAR)923 },
|
|
|
|
{ L"Mu", (WCHAR)924 },
|
|
|
|
{ L"Nu", (WCHAR)925 },
|
|
|
|
{ L"Xi", (WCHAR)926 },
|
|
|
|
{ L"Omicron", (WCHAR)927 },
|
|
|
|
{ L"Pi", (WCHAR)928 },
|
|
|
|
{ L"Rho", (WCHAR)929 },
|
|
|
|
{ L"Sigma", (WCHAR)931 },
|
|
|
|
{ L"Tau", (WCHAR)932 },
|
|
|
|
{ L"Upsilon", (WCHAR)933 },
|
|
|
|
{ L"Phi", (WCHAR)934 },
|
|
|
|
{ L"Chi", (WCHAR)935 },
|
|
|
|
{ L"Psi", (WCHAR)936 },
|
|
|
|
{ L"Omega", (WCHAR)937 },
|
|
|
|
{ L"alpha", (WCHAR)945 },
|
|
|
|
{ L"beta", (WCHAR)946 },
|
|
|
|
{ L"gamma", (WCHAR)947 },
|
|
|
|
{ L"delta", (WCHAR)948 },
|
|
|
|
{ L"epsilon", (WCHAR)949 },
|
|
|
|
{ L"zeta", (WCHAR)950 },
|
|
|
|
{ L"eta", (WCHAR)951 },
|
|
|
|
{ L"theta", (WCHAR)952 },
|
|
|
|
{ L"iota", (WCHAR)953 },
|
|
|
|
{ L"kappa", (WCHAR)954 },
|
|
|
|
{ L"lambda", (WCHAR)955 },
|
|
|
|
{ L"mu", (WCHAR)956 },
|
|
|
|
{ L"nu", (WCHAR)957 },
|
|
|
|
{ L"xi", (WCHAR)958 },
|
|
|
|
{ L"omicron", (WCHAR)959 },
|
|
|
|
{ L"pi", (WCHAR)960 },
|
|
|
|
{ L"rho", (WCHAR)961 },
|
|
|
|
{ L"sigmaf", (WCHAR)962 },
|
|
|
|
{ L"sigma", (WCHAR)963 },
|
|
|
|
{ L"tau", (WCHAR)964 },
|
|
|
|
{ L"upsilon", (WCHAR)965 },
|
|
|
|
{ L"phi", (WCHAR)966 },
|
|
|
|
{ L"chi", (WCHAR)967 },
|
|
|
|
{ L"psi", (WCHAR)968 },
|
|
|
|
{ L"omega", (WCHAR)969 },
|
|
|
|
{ L"thetasym", (WCHAR)977 },
|
|
|
|
{ L"upsih", (WCHAR)978 },
|
|
|
|
{ L"piv", (WCHAR)982 },
|
|
|
|
{ L"bull", (WCHAR)8226 },
|
|
|
|
{ L"hellip", (WCHAR)8230 },
|
|
|
|
{ L"prime", (WCHAR)8242 },
|
|
|
|
{ L"Prime", (WCHAR)8243 },
|
|
|
|
{ L"oline", (WCHAR)8254 },
|
|
|
|
{ L"frasl", (WCHAR)8260 },
|
|
|
|
{ L"weierp", (WCHAR)8472 },
|
|
|
|
{ L"image", (WCHAR)8465 },
|
|
|
|
{ L"real", (WCHAR)8476 },
|
|
|
|
{ L"trade", (WCHAR)8482 },
|
|
|
|
{ L"alefsym", (WCHAR)8501 },
|
|
|
|
{ L"larr", (WCHAR)8592 },
|
|
|
|
{ L"uarr", (WCHAR)8593 },
|
|
|
|
{ L"rarr", (WCHAR)8594 },
|
|
|
|
{ L"darr", (WCHAR)8595 },
|
|
|
|
{ L"harr", (WCHAR)8596 },
|
|
|
|
{ L"crarr", (WCHAR)8629 },
|
|
|
|
{ L"lArr", (WCHAR)8656 },
|
|
|
|
{ L"uArr", (WCHAR)8657 },
|
|
|
|
{ L"rArr", (WCHAR)8658 },
|
|
|
|
{ L"dArr", (WCHAR)8659 },
|
|
|
|
{ L"hArr", (WCHAR)8660 },
|
|
|
|
{ L"forall", (WCHAR)8704 },
|
|
|
|
{ L"part", (WCHAR)8706 },
|
|
|
|
{ L"exist", (WCHAR)8707 },
|
|
|
|
{ L"empty", (WCHAR)8709 },
|
|
|
|
{ L"nabla", (WCHAR)8711 },
|
|
|
|
{ L"isin", (WCHAR)8712 },
|
|
|
|
{ L"notin", (WCHAR)8713 },
|
|
|
|
{ L"ni", (WCHAR)8715 },
|
|
|
|
{ L"prod", (WCHAR)8719 },
|
|
|
|
{ L"sum", (WCHAR)8721 },
|
|
|
|
{ L"minus", (WCHAR)8722 },
|
|
|
|
{ L"lowast", (WCHAR)8727 },
|
|
|
|
{ L"radic", (WCHAR)8730 },
|
|
|
|
{ L"prop", (WCHAR)8733 },
|
|
|
|
{ L"infin", (WCHAR)8734 },
|
|
|
|
{ L"ang", (WCHAR)8736 },
|
|
|
|
{ L"and", (WCHAR)8743 },
|
|
|
|
{ L"or", (WCHAR)8744 },
|
|
|
|
{ L"cap", (WCHAR)8745 },
|
|
|
|
{ L"cup", (WCHAR)8746 },
|
|
|
|
{ L"int", (WCHAR)8747 },
|
|
|
|
{ L"there4", (WCHAR)8756 },
|
|
|
|
{ L"sim", (WCHAR)8764 },
|
|
|
|
{ L"cong", (WCHAR)8773 },
|
|
|
|
{ L"asymp", (WCHAR)8776 },
|
|
|
|
{ L"ne", (WCHAR)8800 },
|
|
|
|
{ L"equiv", (WCHAR)8801 },
|
|
|
|
{ L"le", (WCHAR)8804 },
|
|
|
|
{ L"ge", (WCHAR)8805 },
|
|
|
|
{ L"sub", (WCHAR)8834 },
|
|
|
|
{ L"sup", (WCHAR)8835 },
|
|
|
|
{ L"nsub", (WCHAR)8836 },
|
|
|
|
{ L"sube", (WCHAR)8838 },
|
|
|
|
{ L"supe", (WCHAR)8839 },
|
|
|
|
{ L"oplus", (WCHAR)8853 },
|
|
|
|
{ L"otimes", (WCHAR)8855 },
|
|
|
|
{ L"perp", (WCHAR)8869 },
|
|
|
|
{ L"sdot", (WCHAR)8901 },
|
|
|
|
{ L"lceil", (WCHAR)8968 },
|
|
|
|
{ L"rceil", (WCHAR)8969 },
|
|
|
|
{ L"lfloor", (WCHAR)8970 },
|
|
|
|
{ L"rfloor", (WCHAR)8971 },
|
|
|
|
{ L"lang", (WCHAR)9001 },
|
|
|
|
{ L"rang", (WCHAR)9002 },
|
|
|
|
{ L"loz", (WCHAR)9674 },
|
|
|
|
{ L"spades", (WCHAR)9824 },
|
|
|
|
{ L"clubs", (WCHAR)9827 },
|
|
|
|
{ L"hearts", (WCHAR)9829 },
|
|
|
|
{ L"diams", (WCHAR)9830 }
|
|
|
|
};
|
|
|
|
|
|
|
|
const int entityCount = _countof(entities);
|
2012-02-20 09:37:46 +00:00
|
|
|
g_CERs.rehash(entityCount);
|
2012-02-18 16:02:10 +00:00
|
|
|
for (int i = 0; i < entityCount; ++i)
|
|
|
|
{
|
|
|
|
g_CERs.insert(std::pair<std::wstring, WCHAR>(entities[i].name, entities[i].ch));
|
|
|
|
}
|
2010-08-31 19:49:47 +00:00
|
|
|
|
|
|
|
// for DEBUG
|
|
|
|
//std::map<std::wstring, WCHAR>::const_iterator iter = g_CERs.begin();
|
|
|
|
//for ( ; iter != g_CERs.end(); ++iter)
|
|
|
|
//{
|
|
|
|
// WCHAR buffer[64];
|
|
|
|
// wsprintf(buffer, L"%s - %c", (*iter).first.c_str(), (*iter).second);
|
|
|
|
// Log(buffer);
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
PLUGIN_EXPORT void Initialize(void** data, void* rm)
|
2009-09-12 11:11:40 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
MeasureData* measure = new MeasureData;
|
|
|
|
*data = measure;
|
|
|
|
g_Measures.push_back(measure);
|
2010-08-24 20:23:22 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->skin = RmGetSkin(rm);
|
2010-08-24 20:23:22 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (g_InstanceCount == 0)
|
2009-09-12 11:11:40 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
InitializeCriticalSection(&g_CriticalSection);
|
|
|
|
FillCharacterEntityReferences();
|
* Changed the way to get the information of the multiple display monitors.
This change brings the order of monitors close to the order of "Display Properties" due to using EnumDisplayDevices and EnumDisplaySettings instead of EnumDisplayMonitors. (If EnumDisplayDevices failed, EnumDisplayMonitors is used as before.)
-----
* Added the "Display Monitor" submenu in [Skins Menu]-[Position].
These menus convert the present position to the relative position from the specified monitor.
(But the meter window doesn't move to the specified monitor area immediately. Only converts.)
- "Use default: Primary monitor" removes the @-directive from WindowX/Y.
- @0(@1, @2, ...) adds the specified monitor number to WindowX/Y. @0 means "The Virtual Screen". (http://msdn.microsoft.com/en-us/library/dd145136%28VS.85%29.aspx)
- If "Auto-select based on window position" is checked, the WindowX and WindowY "@n" settings are made automatically based on the position of the meter's window. If a monitor is selected directly using "Display Monitor" in the Rainmeter / skin context menu, this menu is unchecked. This setting can be manually made in either the [Rainmeter] (all configs) or individual config sections of Rainmeter.ini.
AutoSelectScreen
If set to 1, the WindowX and WindowY "@n" settings are made automatically based on the position of the meter's window. If a monitor is selected directly using "Display Monitor" in the Rainmeter / skin context menu, this setting is reset to 0.
-----
* Added the variables for multiple display monitors and the virtual screen.
All X/Y positions are represented in the virtual screen coordinates.
The following variables are for the virtual screen.
#VSCREENAREAX# is the X-position of the left-side of the virtual screen.
#VSCREENAREAY# is the Y-position of the top-side of the virtual screen.
#VSCREENAREAWIDTH# is the width of the virtual screen.
#VSCREENAREAHEIGHT# is the height of the virtual screen.
The following variables are for the PRESENT monitor.
Note that these variables automatically change by the WindowX and WindowY "@n" settings. If "@n" is not set, these variables return the value of the primary monitor.
#WORKAREAX# is the X-position of the left-side of the work area.
#WORKAREAY# is the Y-position of the top-side of the work area.
#WORKAREAWIDTH# is the width of the work area.
#WORKAREAHEIGHT# is the height of the work area.
#SCREENAREAX# is the X-position of the left-side of the monitor screen.
#SCREENAREAY# is the Y-position of the top-side of the monitor screen.
#SCREENAREAWIDTH# is the width of the display resolution.
#SCREENAREAHEIGHT# is the height of the display resolution.
The following variables are for the PRIMARY monitor.
#PWORKAREAX# is the X-position of the left-side of the work area.
#PWORKAREAY# is the Y-position of the top-side of the work area.
#PWORKAREAWIDTH# is the width of the work area.
#PWORKAREAHEIGHT# is the height of the work area.
#PSCREENAREAX# is the X-position of the left-side of the monitor screen. (maybe, always 0)
#PSCREENAREAY# is the Y-position of the top-side of the monitor screen. (maybe, always 0)
#PSCREENAREAWIDTH# is the width of the display resolution.
#PSCREENAREAHEIGHT# is the height of the display resolution.
The following variables are for the SPECIFIED monitor. (@n = @1, @2, ...)
#WORKAREAX@n# is the X-position of the left-side of the work area.
#WORKAREAY@n# is the Y-position of the top-side of the work area.
#WORKAREAWIDTH@n# is the width of the work area.
#WORKAREAHEIGHT@n# is the height of the work area.
#SCREENAREAX@n# is the X-position of the left-side of the monitor screen.
#SCREENAREAY@n# is the Y-position of the top-side of the monitor screen.
#SCREENAREAWIDTH@n# is the width of the display resolution.
#SCREENAREAHEIGHT@n# is the height of the display resolution.
-----
* Other related changes:
- Fixed the problem that the primary monitor isn't recognized correctly.
- Fixed the problem that the information of the multiple display monitors is refreshed excessively.
- For DynamicVariables, when display setting or workarea size has been changed, all variables are now updated to apply changed WORKAREA/SCREENAREA variables.
- Fixed the problem that the "On Desktop" window isn't dragged correctly when the top-left corner of the virtual screen has negative coordinates.
- Changed the way to stick the "On Desktop" window. ("SysListView32/FolderView" is used instead of "Progman/Program Manager".)
-----
* Other changes:
- When the meter window is draggable and isn't dragged, LeftMouseUpAction is now executed.
- Added MouseDoubleClickAction (LeftMouseDoubleClickAction, RightMouseDoubleClickAction, MiddleMouseDoubleClickAction). If MouseDoubleClickAction is empty when mouse button is double-clicked, MouseDownAction is executed instead.
- Fixed the problem that the Meter's hit-test code checks outside the area.
- Changed the way to set the #CURRENTCONFIG#. (CMeterWindow::GetSkinName() is now used instead of parsing the path.)
2009-12-18 05:58:37 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
LPCWSTR proxy = RmReadString(rm, L"ProxyServer", L"");
|
|
|
|
g_InternetHandle = InternetOpen(L"Rainmeter WebParser plugin",
|
|
|
|
*proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
|
|
|
|
*proxy ? proxy : NULL,
|
|
|
|
NULL,
|
|
|
|
0);
|
2011-06-04 08:39:05 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (g_InternetHandle == NULL)
|
* Changed the way to get the information of the multiple display monitors.
This change brings the order of monitors close to the order of "Display Properties" due to using EnumDisplayDevices and EnumDisplaySettings instead of EnumDisplayMonitors. (If EnumDisplayDevices failed, EnumDisplayMonitors is used as before.)
-----
* Added the "Display Monitor" submenu in [Skins Menu]-[Position].
These menus convert the present position to the relative position from the specified monitor.
(But the meter window doesn't move to the specified monitor area immediately. Only converts.)
- "Use default: Primary monitor" removes the @-directive from WindowX/Y.
- @0(@1, @2, ...) adds the specified monitor number to WindowX/Y. @0 means "The Virtual Screen". (http://msdn.microsoft.com/en-us/library/dd145136%28VS.85%29.aspx)
- If "Auto-select based on window position" is checked, the WindowX and WindowY "@n" settings are made automatically based on the position of the meter's window. If a monitor is selected directly using "Display Monitor" in the Rainmeter / skin context menu, this menu is unchecked. This setting can be manually made in either the [Rainmeter] (all configs) or individual config sections of Rainmeter.ini.
AutoSelectScreen
If set to 1, the WindowX and WindowY "@n" settings are made automatically based on the position of the meter's window. If a monitor is selected directly using "Display Monitor" in the Rainmeter / skin context menu, this setting is reset to 0.
-----
* Added the variables for multiple display monitors and the virtual screen.
All X/Y positions are represented in the virtual screen coordinates.
The following variables are for the virtual screen.
#VSCREENAREAX# is the X-position of the left-side of the virtual screen.
#VSCREENAREAY# is the Y-position of the top-side of the virtual screen.
#VSCREENAREAWIDTH# is the width of the virtual screen.
#VSCREENAREAHEIGHT# is the height of the virtual screen.
The following variables are for the PRESENT monitor.
Note that these variables automatically change by the WindowX and WindowY "@n" settings. If "@n" is not set, these variables return the value of the primary monitor.
#WORKAREAX# is the X-position of the left-side of the work area.
#WORKAREAY# is the Y-position of the top-side of the work area.
#WORKAREAWIDTH# is the width of the work area.
#WORKAREAHEIGHT# is the height of the work area.
#SCREENAREAX# is the X-position of the left-side of the monitor screen.
#SCREENAREAY# is the Y-position of the top-side of the monitor screen.
#SCREENAREAWIDTH# is the width of the display resolution.
#SCREENAREAHEIGHT# is the height of the display resolution.
The following variables are for the PRIMARY monitor.
#PWORKAREAX# is the X-position of the left-side of the work area.
#PWORKAREAY# is the Y-position of the top-side of the work area.
#PWORKAREAWIDTH# is the width of the work area.
#PWORKAREAHEIGHT# is the height of the work area.
#PSCREENAREAX# is the X-position of the left-side of the monitor screen. (maybe, always 0)
#PSCREENAREAY# is the Y-position of the top-side of the monitor screen. (maybe, always 0)
#PSCREENAREAWIDTH# is the width of the display resolution.
#PSCREENAREAHEIGHT# is the height of the display resolution.
The following variables are for the SPECIFIED monitor. (@n = @1, @2, ...)
#WORKAREAX@n# is the X-position of the left-side of the work area.
#WORKAREAY@n# is the Y-position of the top-side of the work area.
#WORKAREAWIDTH@n# is the width of the work area.
#WORKAREAHEIGHT@n# is the height of the work area.
#SCREENAREAX@n# is the X-position of the left-side of the monitor screen.
#SCREENAREAY@n# is the Y-position of the top-side of the monitor screen.
#SCREENAREAWIDTH@n# is the width of the display resolution.
#SCREENAREAHEIGHT@n# is the height of the display resolution.
-----
* Other related changes:
- Fixed the problem that the primary monitor isn't recognized correctly.
- Fixed the problem that the information of the multiple display monitors is refreshed excessively.
- For DynamicVariables, when display setting or workarea size has been changed, all variables are now updated to apply changed WORKAREA/SCREENAREA variables.
- Fixed the problem that the "On Desktop" window isn't dragged correctly when the top-left corner of the virtual screen has negative coordinates.
- Changed the way to stick the "On Desktop" window. ("SysListView32/FolderView" is used instead of "Progman/Program Manager".)
-----
* Other changes:
- When the meter window is draggable and isn't dragged, LeftMouseUpAction is now executed.
- Added MouseDoubleClickAction (LeftMouseDoubleClickAction, RightMouseDoubleClickAction, MiddleMouseDoubleClickAction). If MouseDoubleClickAction is empty when mouse button is double-clicked, MouseDownAction is executed instead.
- Fixed the problem that the Meter's hit-test code checks outside the area.
- Changed the way to set the #CURRENTCONFIG#. (CMeterWindow::GetSkinName() is now used instead of parsing the path.)
2009-12-18 05:58:37 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
ShowError(__LINE__);
|
2009-09-12 11:11:40 +00:00
|
|
|
}
|
|
|
|
}
|
2010-08-24 20:23:22 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
++g_InstanceCount;
|
2009-09-12 11:11:40 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
MeasureData* measure = (MeasureData*)data;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->url.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
// No support for DynamicVariables yet
|
|
|
|
return;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->section = RmGetMeasureName(rm);
|
|
|
|
measure->decodeCharacterReference = 0;
|
|
|
|
measure->updateRate = 600;
|
|
|
|
measure->updateCounter = 0;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
/* Read our own settings from the ini-file */
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->url = RmReadString(rm, L"Url", L"", FALSE);
|
|
|
|
measure->regExp = RmReadString(rm, L"RegExp", L"");
|
2012-05-30 05:42:13 +00:00
|
|
|
measure->finishAction = RmReadString(rm, L"FinishAction", L"", FALSE);
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->errorString = RmReadString(rm, L"ErrorString", L"");
|
|
|
|
|
|
|
|
measure->stringIndex = RmReadInt(rm, L"StringIndex", 0);
|
|
|
|
measure->stringIndex2 = RmReadInt(rm, L"StringIndex2", 0);
|
|
|
|
measure->decodeCharacterReference = RmReadInt(rm, L"DecodeCharacterReference", 0);
|
|
|
|
measure->updateRate = RmReadInt(rm, L"UpdateRate", 600);
|
|
|
|
measure->download = 1 == RmReadInt(rm, L"Download", 0);
|
|
|
|
measure->forceReload = 1 == RmReadInt(rm, L"ForceReload", 0);
|
|
|
|
measure->debug = RmReadInt(rm, L"Debug", 0);
|
|
|
|
measure->codepage = RmReadInt(rm, L"CodePage", 0);
|
|
|
|
|
|
|
|
if (measure->download)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->downloadFolder = RmPathToAbsolute(rm, L"DownloadFile\\");
|
|
|
|
measure->downloadFile = RmReadString(rm, L"DownloadFile", L"");
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
else
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->downloadFile.clear();
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->debug == 2)
|
2010-08-31 19:49:47 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->debugFileLocation = RmReadPath(rm, L"Debug2File", L"C:\\WebParserDump.txt");
|
|
|
|
Log(LOG_DEBUG, measure->debugFileLocation.c_str());
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->threadHandle = 0;
|
|
|
|
measure->dlThreadHandle = 0;
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
PLUGIN_EXPORT double Update(void* data)
|
|
|
|
{
|
|
|
|
MeasureData* measure = (MeasureData*)data;
|
|
|
|
double value = 0;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->download && measure->regExp.empty() && measure->url.find(L'[') == std::wstring::npos)
|
2009-08-19 18:07:56 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
// If RegExp is empty download the file that is pointed by the Url
|
|
|
|
if (measure->dlThreadHandle == 0)
|
|
|
|
{
|
|
|
|
if (measure->updateCounter == 0)
|
|
|
|
{
|
|
|
|
// Launch a new thread to fetch the web data
|
|
|
|
unsigned int id;
|
|
|
|
HANDLE threadHandle = (HANDLE)_beginthreadex(NULL, 0, NetworkDownloadThreadProc, measure, 0, &id);
|
|
|
|
if (threadHandle)
|
|
|
|
{
|
|
|
|
measure->dlThreadHandle = threadHandle;
|
|
|
|
}
|
|
|
|
else // error
|
|
|
|
{
|
|
|
|
std::wstring log = L"WebParser.dll: [";
|
|
|
|
log += measure->section;
|
|
|
|
log += L"] Failed to begin download thread.";
|
|
|
|
Log(LOG_ERROR, log.c_str());
|
|
|
|
}
|
|
|
|
}
|
2009-08-19 18:07:56 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->updateCounter++;
|
|
|
|
if (measure->updateCounter >= measure->updateRate)
|
|
|
|
{
|
|
|
|
measure->updateCounter = 0;
|
|
|
|
}
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
// Else download the file pointed by the result string (this is done later)
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
else
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
// Make sure that the thread is not writing to the result at the same time
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->resultString.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
value = wcstod(measure->resultString.c_str(), NULL);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->url.size() > 0 && measure->url.find(L'[') == std::wstring::npos)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
// This is not a reference; need to update.
|
|
|
|
if (measure->threadHandle == 0 && measure->dlThreadHandle == 0)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->updateCounter == 0)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Launch a new thread to fetch the web data
|
2010-08-31 19:49:47 +00:00
|
|
|
unsigned int id;
|
2012-02-18 18:08:18 +00:00
|
|
|
HANDLE threadHandle = (HANDLE)_beginthreadex(NULL, 0, NetworkThreadProc, measure, 0, &id);
|
2010-08-31 19:49:47 +00:00
|
|
|
if (threadHandle)
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->threadHandle = threadHandle;
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
|
|
|
else // error
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
|
|
|
log += L"] Failed to begin thread.";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->updateCounter++;
|
|
|
|
if (measure->updateCounter >= measure->updateRate)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->updateCounter = 0;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
// Fetches the data from the net and parses the page
|
2010-08-31 19:49:47 +00:00
|
|
|
unsigned __stdcall NetworkThreadProc(void* pParam)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
MeasureData* measure = (MeasureData*)pParam;
|
2009-02-10 18:37:48 +00:00
|
|
|
DWORD dwSize = 0;
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
BYTE* data = DownloadUrl(measure->url, &dwSize, measure->forceReload);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
if (data)
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->debug == 2)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Dump to a file
|
2009-09-21 17:02:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
FILE* file = _wfopen(measure->debugFileLocation.c_str(), L"wb");
|
2010-02-03 08:01:50 +00:00
|
|
|
if (file)
|
|
|
|
{
|
|
|
|
fwrite(data, sizeof(BYTE), dwSize, file);
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Failed to dump debug data: ";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->debugFileLocation;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-02-03 08:01:50 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
ParseData(measure, (LPCSTR)data, dwSize);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
delete [] data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2012-02-18 18:08:18 +00:00
|
|
|
CloseHandle(measure->threadHandle);
|
|
|
|
measure->threadHandle = 0;
|
2009-02-10 18:37:48 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
return 0; // thread completed successfully
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Parse the value from the data
|
|
|
|
pcre* re;
|
|
|
|
const char* error;
|
|
|
|
int erroffset;
|
|
|
|
int ovector[OVECCOUNT];
|
|
|
|
int rc;
|
|
|
|
int flags = PCRE_UTF8;
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->codepage == 0)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
flags = 0;
|
|
|
|
}
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Compile the regular expression in the first argument
|
|
|
|
re = pcre_compile(
|
2012-02-18 18:08:18 +00:00
|
|
|
ConvertWideToUTF8(measure->regExp.c_str()).c_str(), // the pattern
|
2009-02-10 18:37:48 +00:00
|
|
|
flags, // default options
|
|
|
|
&error, // for error message
|
|
|
|
&erroffset, // for error offset
|
|
|
|
NULL); // use default character tables
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
if (re != NULL)
|
|
|
|
{
|
|
|
|
// Compilation succeeded: match the subject in the second argument
|
|
|
|
std::string utf8Data;
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->codepage == 1200) // 1200 = UTF-16LE
|
2011-06-30 09:04:49 +00:00
|
|
|
{
|
|
|
|
// Must convert the data to utf8
|
|
|
|
utf8Data = ConvertWideToUTF8((LPCWSTR)parseData);
|
|
|
|
parseData = utf8Data.c_str();
|
2011-10-10 08:20:31 +00:00
|
|
|
dwSize = utf8Data.length();
|
2011-06-30 09:04:49 +00:00
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
else if (measure->codepage != CP_UTF8 && measure->codepage != 0) // 0 = CP_ACP
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Must convert the data to utf8
|
2012-02-18 18:08:18 +00:00
|
|
|
utf8Data = ConvertAsciiToUTF8(parseData, measure->codepage);
|
2009-02-10 18:37:48 +00:00
|
|
|
parseData = utf8Data.c_str();
|
2011-10-10 08:20:31 +00:00
|
|
|
dwSize = utf8Data.length();
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = pcre_exec(
|
|
|
|
re, // the compiled pattern
|
|
|
|
NULL, // no extra data - we didn't study the pattern
|
|
|
|
parseData, // the subject string
|
|
|
|
dwSize, // the length of the subject
|
|
|
|
0, // start at offset 0 in the subject
|
|
|
|
0, // default options
|
|
|
|
ovector, // output vector for substring information
|
|
|
|
OVECCOUNT); // number of elements in the output vector
|
2011-03-29 19:21:57 +00:00
|
|
|
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
if (rc >= 0)
|
|
|
|
{
|
|
|
|
if (rc == 0)
|
|
|
|
{
|
|
|
|
// The output vector wasn't big enough
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Too many substrings!";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->stringIndex < rc)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->debug != 0)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-08-31 19:49:47 +00:00
|
|
|
for (int i = 0; i < rc; ++i)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-02-03 08:01:50 +00:00
|
|
|
const char* substring_start = parseData + ovector[2 * i];
|
2009-02-10 18:37:48 +00:00
|
|
|
int substring_length = ovector[2 * i + 1] - ovector[2 * i];
|
|
|
|
substring_length = min(substring_length, 256);
|
|
|
|
std::string tmpStr(substring_start, substring_length);
|
2010-09-21 14:13:43 +00:00
|
|
|
|
|
|
|
WCHAR buffer[32];
|
|
|
|
wsprintf(buffer, L"%2d", i);
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] (Index ";
|
|
|
|
log += buffer;
|
|
|
|
log += L") ";
|
|
|
|
log += ConvertUTF8ToWide(tmpStr.c_str());
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_DEBUG, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
const char* substring_start = parseData + ovector[2 * measure->stringIndex];
|
|
|
|
int substring_length = ovector[2 * measure->stringIndex + 1] - ovector[2 * measure->stringIndex];
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2010-02-03 08:01:50 +00:00
|
|
|
std::string szResult(substring_start, substring_length);
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->resultString = DecodeReferences(ConvertUTF8ToWide(szResult.c_str()), measure->decodeCharacterReference);
|
2009-02-10 18:37:48 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Not enough substrings!";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_WARNING, log.c_str());
|
2010-08-10 12:21:46 +00:00
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
// Clear the old result
|
2010-08-10 12:21:46 +00:00
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->resultString.clear();
|
|
|
|
if (measure->download)
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->downloadFile.empty()) // cache mode
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->downloadedFile.empty())
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
|
|
|
// Delete old downloaded file
|
2012-02-18 18:08:18 +00:00
|
|
|
DeleteFile(measure->downloadedFile.c_str());
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->downloadedFile.clear();
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
2010-08-10 12:21:46 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update the references
|
2012-02-18 18:08:18 +00:00
|
|
|
std::vector<MeasureData*>::iterator i = g_Measures.begin();
|
2009-02-10 18:37:48 +00:00
|
|
|
std::wstring compareStr = L"[";
|
2012-02-18 18:08:18 +00:00
|
|
|
compareStr += measure->section;
|
2009-02-10 18:37:48 +00:00
|
|
|
compareStr += L"]";
|
2012-02-18 18:08:18 +00:00
|
|
|
for ( ; i != g_Measures.end(); ++i)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->skin == (*i)->skin &&
|
|
|
|
(*i)->url.find(compareStr) != std::wstring::npos)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if ((*i)->stringIndex < rc)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
const char* substring_start = parseData + ovector[2 * (*i)->stringIndex];
|
|
|
|
int substring_length = ovector[2 * (*i)->stringIndex + 1] - ovector[2 * (*i)->stringIndex];
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-02-03 08:01:50 +00:00
|
|
|
std::string szResult(substring_start, substring_length);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!(*i)->regExp.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Change the index and parse the substring
|
2012-02-18 18:08:18 +00:00
|
|
|
int index = (*i)->stringIndex;
|
|
|
|
(*i)->stringIndex = (*i)->stringIndex2;
|
|
|
|
ParseData((*i), szResult.c_str(), szResult.length());
|
|
|
|
(*i)->stringIndex = index;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-29 19:21:57 +00:00
|
|
|
// Set the result
|
2009-02-10 18:37:48 +00:00
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Substitude the [measure] with szResult
|
2010-08-19 09:24:25 +00:00
|
|
|
std::wstring wzResult = ConvertUTF8ToWide(szResult.c_str());
|
2012-02-18 18:08:18 +00:00
|
|
|
std::wstring wzUrl = (*i)->url;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
wzUrl.replace(wzUrl.find(compareStr), compareStr.size(), wzResult);
|
2012-02-18 18:08:18 +00:00
|
|
|
(*i)->resultString = DecodeReferences(wzUrl, (*i)->decodeCharacterReference);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
// Start download threads for the references
|
2012-02-18 18:08:18 +00:00
|
|
|
if ((*i)->download)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Start the download thread
|
2010-08-31 19:49:47 +00:00
|
|
|
unsigned int id;
|
2012-02-18 18:08:18 +00:00
|
|
|
HANDLE threadHandle = (HANDLE)_beginthreadex(NULL, 0, NetworkDownloadThreadProc, (*i), 0, &id);
|
2010-08-31 19:49:47 +00:00
|
|
|
if (threadHandle)
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
(*i)->dlThreadHandle = threadHandle;
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
|
|
|
else // error
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += (*i)->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Failed to begin download thread.";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += (*i)->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Not enough substrings!";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_WARNING, log.c_str());
|
2010-08-10 10:51:19 +00:00
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
// Clear the old result
|
2010-08-10 10:51:19 +00:00
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2012-02-18 18:08:18 +00:00
|
|
|
(*i)->resultString.clear();
|
|
|
|
if ((*i)->download)
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if ((*i)->downloadFile.empty()) // cache mode
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!(*i)->downloadedFile.empty())
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
|
|
|
// Delete old downloaded file
|
2012-02-18 18:08:18 +00:00
|
|
|
DeleteFile((*i)->downloadedFile.c_str());
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
(*i)->downloadedFile.clear();
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
2010-08-10 10:51:19 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Matching failed: handle error cases
|
2010-09-21 14:13:43 +00:00
|
|
|
WCHAR buffer[32];
|
|
|
|
wsprintf(buffer, L"%d", rc);
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Matching error! (";
|
|
|
|
log += buffer;
|
|
|
|
log += L")\n";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->resultString = measure->errorString;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
// Update the references
|
2012-02-18 18:08:18 +00:00
|
|
|
std::vector<MeasureData*>::iterator i = g_Measures.begin();
|
2009-02-10 18:37:48 +00:00
|
|
|
std::wstring compareStr = L"[";
|
2012-02-18 18:08:18 +00:00
|
|
|
compareStr += measure->section;
|
2009-02-10 18:37:48 +00:00
|
|
|
compareStr += L"]";
|
2012-02-18 18:08:18 +00:00
|
|
|
for ( ; i != g_Measures.end(); ++i)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (((*i)->url.find(compareStr) != std::wstring::npos) && (measure->skin == (*i)->skin))
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
(*i)->resultString = (*i)->errorString;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
2010-08-24 20:23:22 +00:00
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
// Release memory used for the compiled pattern
|
2010-08-24 20:23:22 +00:00
|
|
|
pcre_free(re);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Compilation failed: print the error message and exit
|
2010-09-21 14:13:43 +00:00
|
|
|
WCHAR buffer[32];
|
|
|
|
wsprintf(buffer, L"%d", erroffset);
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] PCRE compilation failed at offset ";
|
|
|
|
log += buffer;
|
|
|
|
log += L": ";
|
|
|
|
log += ConvertAsciiToWide(error);
|
|
|
|
log += L"\n";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->download)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Start the download thread
|
2010-08-31 19:49:47 +00:00
|
|
|
unsigned int id;
|
2012-02-18 18:08:18 +00:00
|
|
|
HANDLE threadHandle = (HANDLE)_beginthreadex(NULL, 0, NetworkDownloadThreadProc, measure, 0, &id);
|
2010-08-31 19:49:47 +00:00
|
|
|
if (threadHandle)
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->dlThreadHandle = threadHandle;
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
|
|
|
else // error
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Failed to begin download thread.";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-08-31 19:49:47 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->finishAction.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
RmExecute(measure->skin, measure->finishAction.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
// Downloads file from the net
|
2010-08-31 19:49:47 +00:00
|
|
|
unsigned __stdcall NetworkDownloadThreadProc(void* pParam)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
MeasureData* measure = (MeasureData*)pParam;
|
|
|
|
const bool download = !measure->downloadFile.empty();
|
2010-09-21 14:13:43 +00:00
|
|
|
bool ready = false;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
std::wstring url;
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->regExp.empty() && measure->resultString.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->url.empty() && measure->url[0] != L'[')
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
url = measure->url;
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2012-02-18 18:08:18 +00:00
|
|
|
url = measure->resultString;
|
2009-02-10 18:37:48 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2010-01-12 21:45:47 +00:00
|
|
|
std::wstring::size_type pos = url.find(L':');
|
|
|
|
if (pos == std::wstring::npos && !url.empty()) // No protocol
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Add the base url to the string
|
2010-01-12 21:45:47 +00:00
|
|
|
if (url[0] == L'/')
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Absolute path
|
2012-02-18 18:08:18 +00:00
|
|
|
pos = measure->url.find(L'/', 7); // Assume "http://" (=7)
|
2010-01-12 21:45:47 +00:00
|
|
|
if (pos != std::wstring::npos)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
std::wstring path(measure->url.substr(0, pos));
|
2009-02-10 18:37:48 +00:00
|
|
|
url = path + url;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Relative path
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
pos = measure->url.rfind(L'/');
|
2010-01-12 21:45:47 +00:00
|
|
|
if (pos != std::wstring::npos)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
std::wstring path(measure->url.substr(0, pos + 1));
|
2009-02-10 18:37:48 +00:00
|
|
|
url = path + url;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!url.empty())
|
|
|
|
{
|
|
|
|
// Create the filename
|
2010-01-12 21:45:47 +00:00
|
|
|
WCHAR buffer[MAX_PATH] = {0};
|
|
|
|
std::wstring fullpath, directory;
|
|
|
|
|
|
|
|
if (download) // download mode
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
PathCanonicalize(buffer, measure->downloadFile.c_str());
|
2010-01-12 21:45:47 +00:00
|
|
|
|
|
|
|
std::wstring path = buffer;
|
|
|
|
std::wstring::size_type pos = path.find_first_not_of(L'\\');
|
|
|
|
if (pos != std::wstring::npos)
|
|
|
|
{
|
2011-07-14 00:26:53 +00:00
|
|
|
path.erase(0, pos);
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
PathCanonicalize(buffer, measure->downloadFolder.c_str());
|
2010-01-12 21:45:47 +00:00
|
|
|
CreateDirectory(buffer, NULL); // Make sure that the folder exists
|
|
|
|
|
|
|
|
wcscat(buffer, path.c_str());
|
|
|
|
|
|
|
|
if (buffer[wcslen(buffer)-1] != L'\\') // path is a file
|
|
|
|
{
|
|
|
|
fullpath = buffer;
|
|
|
|
PathRemoveFileSpec(buffer);
|
|
|
|
}
|
|
|
|
PathAddBackslash(buffer);
|
|
|
|
}
|
|
|
|
else // cache mode
|
|
|
|
{
|
|
|
|
GetTempPath(MAX_PATH, buffer);
|
|
|
|
wcscat(buffer, L"Rainmeter-Cache\\"); // "%TEMP%\Rainmeter-Cache\"
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
CreateDirectory(buffer, NULL); // Make sure that the folder exists
|
2010-01-12 21:45:47 +00:00
|
|
|
directory = buffer;
|
|
|
|
|
|
|
|
if (fullpath.empty())
|
|
|
|
{
|
|
|
|
fullpath = directory;
|
|
|
|
|
|
|
|
std::wstring::size_type pos2 = url.find_first_of(L"?#");
|
|
|
|
std::wstring::size_type pos1 = url.find_last_of(L'/', pos2);
|
|
|
|
pos1 = (pos1 != std::wstring::npos) ? pos1 + 1 : 0;
|
|
|
|
|
|
|
|
std::wstring name;
|
|
|
|
if (pos2 != std::wstring::npos)
|
|
|
|
{
|
2011-07-14 00:26:53 +00:00
|
|
|
name.assign(url, pos1, pos2 - pos1);
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-07-14 00:26:53 +00:00
|
|
|
name.assign(url, pos1, url.length() - pos1);
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!name.empty())
|
|
|
|
{
|
|
|
|
// Replace reserved characters to "_"
|
|
|
|
pos1 = 0;
|
|
|
|
while ((pos1 = name.find_first_of(L"\\/:*?\"<>|", pos1)) != std::wstring::npos)
|
|
|
|
{
|
|
|
|
name[pos1] = L'_';
|
|
|
|
}
|
|
|
|
fullpath += name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fullpath += L"index";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-21 14:13:43 +00:00
|
|
|
ready = true;
|
|
|
|
|
2010-01-12 21:45:47 +00:00
|
|
|
if (download) // download mode
|
|
|
|
{
|
2010-09-21 14:13:43 +00:00
|
|
|
std::wstring log;
|
2010-01-12 21:45:47 +00:00
|
|
|
|
|
|
|
if (!PathFileExists(directory.c_str()) || !PathIsDirectory(directory.c_str()))
|
|
|
|
{
|
|
|
|
ready = false;
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2011-08-19 13:33:49 +00:00
|
|
|
log += L"] Directory does not exist: ";
|
2010-09-21 14:13:43 +00:00
|
|
|
log += directory;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
|
|
|
else if (PathIsDirectory(fullpath.c_str()))
|
|
|
|
{
|
|
|
|
ready = false;
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Path is a directory, not a file: ";
|
|
|
|
log += fullpath;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
2010-09-21 14:13:43 +00:00
|
|
|
else if (PathFileExists(fullpath.c_str()))
|
2010-01-12 21:45:47 +00:00
|
|
|
{
|
2010-09-21 14:13:43 +00:00
|
|
|
DWORD attr = GetFileAttributes(fullpath.c_str());
|
|
|
|
if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY))
|
2010-01-12 21:45:47 +00:00
|
|
|
{
|
|
|
|
ready = false;
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] File is READ-ONLY: ";
|
|
|
|
log += fullpath;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // cache mode
|
|
|
|
{
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
|
|
|
|
|
|
if (PathFileExists(fullpath.c_str()))
|
|
|
|
{
|
|
|
|
std::wstring::size_type pos = fullpath.find_last_of(L'.');
|
|
|
|
|
|
|
|
std::wstring path, ext;
|
|
|
|
if (pos != std::wstring::npos)
|
|
|
|
{
|
2011-07-14 00:26:53 +00:00
|
|
|
path.assign(fullpath, 0, pos);
|
|
|
|
ext.assign(fullpath, pos, fullpath.length() - pos);
|
2010-01-12 21:45:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
path = fullpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assign a serial number
|
2010-09-21 14:13:43 +00:00
|
|
|
int i = 1;
|
2010-01-12 21:45:47 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
wsprintf(buffer, L"_%i", i++);
|
|
|
|
|
|
|
|
fullpath = path;
|
|
|
|
fullpath += buffer;
|
|
|
|
if (!ext.empty())
|
|
|
|
{
|
|
|
|
fullpath += ext;
|
|
|
|
}
|
|
|
|
} while (PathFileExists(fullpath.c_str()));
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-01-12 21:45:47 +00:00
|
|
|
// Create empty file
|
|
|
|
HANDLE hFile = CreateFile(fullpath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
|
|
|
|
|
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ready)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-01-12 21:45:47 +00:00
|
|
|
// Delete IE cache before download if "SyncMode5" is not 3 (every visit to the page)
|
|
|
|
{
|
|
|
|
// Check "Temporary Internet Files" sync mode (SyncMode5)
|
|
|
|
// Values:
|
|
|
|
// Every visit to the page 3
|
|
|
|
// Every time you start Internet Explorer 2
|
|
|
|
// Automatically (default) 4
|
|
|
|
// Never 0
|
|
|
|
// http://support.microsoft.com/kb/263070/en
|
|
|
|
|
|
|
|
HKEY hKey;
|
|
|
|
LONG ret;
|
|
|
|
DWORD mode;
|
|
|
|
|
|
|
|
ret = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_QUERY_VALUE, &hKey);
|
|
|
|
if (ret == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
DWORD size = sizeof(mode);
|
|
|
|
ret = RegQueryValueEx(hKey, L"SyncMode5", NULL, NULL, (LPBYTE)&mode, &size);
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret != ERROR_SUCCESS || mode != 3)
|
|
|
|
{
|
|
|
|
std::wstring::size_type pos = url.find_first_of(L'#');
|
|
|
|
|
|
|
|
if (pos != std::wstring::npos)
|
|
|
|
{
|
|
|
|
DeleteUrlCacheEntry(url.substr(0, pos).c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DeleteUrlCacheEntry(url.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
// Write some log info
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Downloading url ";
|
|
|
|
log += url;
|
|
|
|
log += L" to ";
|
|
|
|
log += fullpath;
|
|
|
|
log += L"\n";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_DEBUG, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-01-12 21:45:47 +00:00
|
|
|
HRESULT resultCoInitialize = CoInitialize(NULL); // requires before calling URLDownloadToFile function
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
// Download the file
|
2010-01-12 21:45:47 +00:00
|
|
|
HRESULT result = URLDownloadToFile(NULL, url.c_str(), fullpath.c_str(), NULL, NULL);
|
|
|
|
if (result == S_OK)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2010-01-12 21:45:47 +00:00
|
|
|
|
2010-09-21 14:13:43 +00:00
|
|
|
if (!download) // cache mode
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->downloadedFile.empty())
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
|
|
|
// Delete old downloaded file
|
2012-02-18 18:08:18 +00:00
|
|
|
DeleteFile(measure->downloadedFile.c_str());
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-12 21:45:47 +00:00
|
|
|
// Convert LFN to 8.3 filename if the path contains blank character
|
|
|
|
if (fullpath.find_first_of(L' ') != std::wstring::npos)
|
|
|
|
{
|
|
|
|
DWORD size = GetShortPathName(fullpath.c_str(), buffer, MAX_PATH);
|
|
|
|
if (size > 0 && size <= MAX_PATH)
|
|
|
|
{
|
|
|
|
fullpath = buffer;
|
|
|
|
}
|
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->downloadedFile = fullpath;
|
2010-01-12 21:45:47 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->finishAction.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
RmExecute(measure->skin, measure->finishAction.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-21 14:13:43 +00:00
|
|
|
ready = false;
|
|
|
|
|
2010-01-12 21:45:47 +00:00
|
|
|
if (!download) // cache mode
|
|
|
|
{
|
|
|
|
// Delete empty file
|
|
|
|
DeleteFile(fullpath.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
wsprintf(buffer, L"result=0x%08X, COM=0x%08X", result, resultCoInitialize);
|
2010-09-21 14:13:43 +00:00
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Download failed (";
|
|
|
|
log += buffer;
|
|
|
|
log += L"): ";
|
|
|
|
log += url;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
2010-01-12 21:45:47 +00:00
|
|
|
|
|
|
|
if (SUCCEEDED(resultCoInitialize))
|
|
|
|
{
|
|
|
|
CoUninitialize();
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] Download failed: ";
|
|
|
|
log += url;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring log = L"WebParser.dll: [";
|
2012-02-18 18:08:18 +00:00
|
|
|
log += measure->section;
|
2010-09-21 14:13:43 +00:00
|
|
|
log += L"] The url is empty.\n";
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, log.c_str());
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!ready) // download failed
|
|
|
|
{
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
|
|
|
|
|
|
if (!download) // cache mode
|
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
if (!measure->downloadedFile.empty())
|
2010-09-21 14:13:43 +00:00
|
|
|
{
|
|
|
|
// Delete old downloaded file
|
2012-02-18 18:08:18 +00:00
|
|
|
DeleteFile(measure->downloadedFile.c_str());
|
2010-09-21 14:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear old downloaded filename
|
2012-02-18 18:08:18 +00:00
|
|
|
measure->downloadedFile.clear();
|
2010-09-21 14:13:43 +00:00
|
|
|
|
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2012-02-18 18:08:18 +00:00
|
|
|
CloseHandle(measure->dlThreadHandle);
|
|
|
|
measure->dlThreadHandle = 0;
|
2009-02-10 18:37:48 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
return 0; // thread completed successfully
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
PLUGIN_EXPORT LPCWSTR GetString(void* data)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
MeasureData* measure = (MeasureData*)data;
|
2009-02-10 18:37:48 +00:00
|
|
|
static std::wstring resultString;
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
|
|
if (measure->download)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
resultString = measure->downloadedFile;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
resultString = measure->resultString;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
2012-02-18 18:08:18 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
return resultString.c_str();
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
PLUGIN_EXPORT void Finalize(void* data)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
MeasureData* measure = (MeasureData*)data;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->threadHandle)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
// Thread is killed inside critical section so that itself is not inside one when it is terminated
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
TerminateThread(measure->threadHandle, 0);
|
|
|
|
measure->threadHandle = NULL;
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->dlThreadHandle)
|
|
|
|
{
|
|
|
|
// Thread is killed inside critical section so that itself is not inside one when it is terminated
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
TerminateThread(measure->dlThreadHandle, 0);
|
|
|
|
measure->dlThreadHandle = NULL;
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
if (measure->downloadFile.empty()) // cache mode
|
|
|
|
{
|
|
|
|
if (!measure->downloadedFile.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
// Delete the file
|
|
|
|
DeleteFile(measure->downloadedFile.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
delete measure;
|
|
|
|
std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure);
|
|
|
|
g_Measures.erase(iter);
|
|
|
|
|
|
|
|
--g_InstanceCount;
|
|
|
|
if (g_InstanceCount == 0)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Last one, close all handles
|
2012-02-18 18:08:18 +00:00
|
|
|
if (g_InternetHandle)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2012-02-18 18:08:18 +00:00
|
|
|
InternetCloseHandle(g_InternetHandle);
|
|
|
|
g_InternetHandle = NULL;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2010-08-31 19:49:47 +00:00
|
|
|
g_CERs.clear();
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Last instance deletes the critical section
|
|
|
|
DeleteCriticalSection(&g_CriticalSection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Downloads the given url and returns the webpage as dynamically allocated string.
|
|
|
|
You need to delete the returned string after use!
|
|
|
|
*/
|
2009-08-19 18:07:56 +00:00
|
|
|
BYTE* DownloadUrl(std::wstring& url, DWORD* dwDataSize, bool forceReload)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
HINTERNET hUrlDump;
|
|
|
|
DWORD dwSize;
|
|
|
|
BYTE* lpData;
|
|
|
|
BYTE* lpOutPut;
|
|
|
|
BYTE* lpHolding = NULL;
|
|
|
|
int nCounter = 1;
|
|
|
|
int nBufferSize;
|
|
|
|
const int CHUNK_SIZE = 8192;
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring err = L"WebParser.dll: Fetching: " + url;
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_DEBUG, err.c_str());
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-08-19 18:07:56 +00:00
|
|
|
DWORD flags = INTERNET_FLAG_RESYNCHRONIZE;
|
|
|
|
if (forceReload)
|
|
|
|
{
|
|
|
|
flags = INTERNET_FLAG_RELOAD;
|
|
|
|
}
|
|
|
|
|
2012-02-18 18:08:18 +00:00
|
|
|
hUrlDump = InternetOpenUrl(g_InternetHandle, url.c_str(), NULL, NULL, flags, 0);
|
2009-02-10 18:37:48 +00:00
|
|
|
if (hUrlDump == NULL)
|
|
|
|
{
|
2010-09-17 08:47:22 +00:00
|
|
|
if (_wcsnicmp(url.c_str(), L"file://", 7) == 0) // file scheme
|
2010-02-03 08:01:50 +00:00
|
|
|
{
|
2010-08-19 09:24:25 +00:00
|
|
|
std::string urlACP = ConvertWideToAscii(url.c_str());
|
2012-02-18 18:08:18 +00:00
|
|
|
hUrlDump = InternetOpenUrlA(g_InternetHandle, urlACP.c_str(), NULL, NULL, flags, 0);
|
2010-02-03 08:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (hUrlDump == NULL)
|
|
|
|
{
|
|
|
|
ShowError(__LINE__);
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*dwDataSize = 0;
|
|
|
|
|
2010-08-31 19:49:47 +00:00
|
|
|
// Allocate the buffer.
|
|
|
|
lpData = new BYTE[CHUNK_SIZE];
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
// Read the data.
|
|
|
|
if (!InternetReadFile(hUrlDump, (LPVOID)lpData, CHUNK_SIZE, &dwSize))
|
|
|
|
{
|
|
|
|
ShowError(__LINE__);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Check if all of the data has been read. This should
|
|
|
|
// never get called on the first time through the loop.
|
|
|
|
if (dwSize == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Determine the buffer size to hold the new data and the data
|
|
|
|
// already written (if any).
|
2010-08-31 19:49:47 +00:00
|
|
|
nBufferSize = *dwDataSize + dwSize;
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Allocate the output buffer.
|
2011-06-30 09:18:00 +00:00
|
|
|
lpOutPut = new BYTE[nBufferSize + 3];
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Make sure the buffer is not the initial buffer.
|
|
|
|
if (lpHolding != NULL)
|
|
|
|
{
|
|
|
|
// Copy the data in the holding buffer.
|
|
|
|
memcpy(lpOutPut, lpHolding, *dwDataSize);
|
|
|
|
|
|
|
|
// Delete the old buffer
|
|
|
|
delete [] lpHolding;
|
|
|
|
|
|
|
|
lpHolding = lpOutPut;
|
|
|
|
lpOutPut = lpOutPut + *dwDataSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lpHolding = lpOutPut;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the data buffer.
|
|
|
|
memcpy(lpOutPut, lpData, dwSize);
|
|
|
|
|
|
|
|
*dwDataSize += dwSize;
|
|
|
|
|
2011-06-30 09:18:00 +00:00
|
|
|
// End with triple null
|
2009-02-10 18:37:48 +00:00
|
|
|
lpOutPut[dwSize] = 0;
|
|
|
|
lpOutPut[dwSize + 1] = 0;
|
2011-06-30 09:18:00 +00:00
|
|
|
lpOutPut[dwSize + 2] = 0;
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Increment the number of buffers read.
|
2010-08-31 19:49:47 +00:00
|
|
|
++nCounter;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-08-31 19:49:47 +00:00
|
|
|
// Clear the buffer
|
|
|
|
memset(lpData, 0, CHUNK_SIZE);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
} while (TRUE);
|
2011-03-29 19:21:57 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Close the HINTERNET handle.
|
|
|
|
InternetCloseHandle(hUrlDump);
|
|
|
|
|
2010-08-31 19:49:47 +00:00
|
|
|
// Delete the existing buffers.
|
|
|
|
delete [] lpData;
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Return.
|
|
|
|
return lpHolding;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Writes the last error to log.
|
|
|
|
*/
|
|
|
|
void ShowError(int lineNumber, WCHAR* errorMsg)
|
|
|
|
{
|
2010-02-03 08:01:50 +00:00
|
|
|
DWORD dwErr = GetLastError();
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
WCHAR buffer[16];
|
|
|
|
wsprintf(buffer, L"%i", lineNumber);
|
|
|
|
|
2011-10-12 13:34:04 +00:00
|
|
|
std::wstring err = L"WebParser.dll: (";
|
2009-02-10 18:37:48 +00:00
|
|
|
err += buffer;
|
|
|
|
err += L") ";
|
|
|
|
|
|
|
|
if (errorMsg == NULL)
|
|
|
|
{
|
2011-03-29 19:21:57 +00:00
|
|
|
if (dwErr == ERROR_INTERNET_EXTENDED_ERROR)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-08-31 19:49:47 +00:00
|
|
|
WCHAR szBuffer[1024];
|
|
|
|
DWORD dwError, dwLen = 1024;
|
2009-02-10 18:37:48 +00:00
|
|
|
if (InternetGetLastResponseInfo(&dwError, szBuffer, &dwLen))
|
|
|
|
{
|
|
|
|
err += szBuffer;
|
2010-02-03 08:01:50 +00:00
|
|
|
wsprintf(buffer, L"%i", dwError);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
2010-02-03 08:01:50 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
err += L"Unknown error";
|
|
|
|
wsprintf(buffer, L"%i", dwErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
err += L" (ErrorCode=";
|
|
|
|
err += buffer;
|
|
|
|
err += L")";
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-02-03 08:01:50 +00:00
|
|
|
LPVOID lpMsgBuf = NULL;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
FormatMessage(
|
|
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
2010-02-03 08:01:50 +00:00
|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
|
|
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
2011-02-18 13:49:27 +00:00
|
|
|
GetModuleHandle(L"wininet"),
|
2009-02-10 18:37:48 +00:00
|
|
|
dwErr,
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
|
|
(LPTSTR) &lpMsgBuf,
|
|
|
|
0,
|
2011-03-29 19:21:57 +00:00
|
|
|
NULL
|
2009-02-10 18:37:48 +00:00
|
|
|
);
|
|
|
|
|
2011-03-29 19:21:57 +00:00
|
|
|
if (lpMsgBuf == NULL)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-02-03 08:01:50 +00:00
|
|
|
err += L"Unknown error";
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err += (LPTSTR)lpMsgBuf;
|
|
|
|
LocalFree(lpMsgBuf);
|
|
|
|
}
|
2010-02-03 08:01:50 +00:00
|
|
|
|
|
|
|
wsprintf(buffer, L"%i", dwErr);
|
|
|
|
err += L" (ErrorCode=";
|
|
|
|
err += buffer;
|
|
|
|
err += L")";
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err += errorMsg;
|
|
|
|
}
|
|
|
|
|
2011-08-19 13:33:49 +00:00
|
|
|
Log(LOG_ERROR, err.c_str());
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-12 13:34:04 +00:00
|
|
|
Writes the log to a file
|
2009-02-10 18:37:48 +00:00
|
|
|
*/
|
2011-08-19 13:33:49 +00:00
|
|
|
void Log(int level, const WCHAR* string)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2011-10-12 13:34:04 +00:00
|
|
|
LSLog(level, NULL, string);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UINT GetPluginVersion()
|
|
|
|
{
|
2010-08-31 19:49:47 +00:00
|
|
|
return 1013;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LPCTSTR GetPluginAuthor()
|
|
|
|
{
|
|
|
|
return L"Rainy (rainy@iki.fi)";
|
|
|
|
}
|