PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
	ChildMeasure* child = new ChildMeasure;
	*data = child;

	void* skin = RmGetSkin(rm);

	LPCWSTR parentName = RmReadString(rm, L"ParentName", L"");
	if (!*parentName)
	{
		child->parent = new ParentMeasure;
		child->parent->name = RmGetMeasureName(rm);
		child->parent->skin = skin;
		child->parent->ownerChild = child;
		g_ParentMeasures.push_back(child->parent);
	}
	else
	{
		// Find parent using name AND the skin handle to be sure that it's the right one
		std::vector<ParentMeasure*>::const_iterator iter = g_ParentMeasures.begin();
		for ( ; iter != g_ParentMeasures.end(); ++iter)
		{
			if (_wcsicmp((*iter)->name, parentName) == 0 &&
				(*iter)->skin == skin)
			{
				child->parent = (*iter);
				return;
			}
		}

		RmLog(LOG_ERROR, L"ParentChild.dll: Invalid ParentName=");
	}
}
Пример #2
0
PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
	MeasureData* measure = new MeasureData(RmGetMeasureName(rm));
	*data = measure;
	g_Measures.push_back(measure);

	void* skin = RmGetSkin(rm);

	LPCWSTR str = RmReadString(rm, L"Folder", L"", FALSE);
	if (*str == L'[')
	{
		int len = wcslen(str);
		for (auto iter = g_Measures.cbegin(); iter != g_Measures.cend(); ++iter)
		{
			if ((*iter)->folder &&
				(*iter)->folder->GetSkin() == skin &&
				wcsncmp(&str[1], (*iter)->section, len - 2) == 0)
			{
				measure->folder = (*iter)->folder;
				measure->folder->AddInstance();
				return;
			}
		}
	}

	measure->folder = new CFolderInfo(skin);
	measure->parent = true;
}
Пример #3
0
static PyObject *Rainmeter_RmGetMeasureName(RainmeterObject *self)
{
	LPCWSTR result = RmGetMeasureName(self->rm);
	if (result == NULL)
	{
		Py_INCREF(Py_None);
		return Py_None;
	}
	return PyUnicode_FromWideChar(result, -1);
}
Пример #4
0
PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args)
{
	MeasureData* measure = (MeasureData*)data;

	// Kill the threads (if any) and reset the update counter
	if (_wcsicmp(args, L"UPDATE") == 0)
	{
		if (measure->threadHandle)
		{
			// Thread is killed inside critical section so that itself is not inside one when it is terminated
			EnterCriticalSection(&g_CriticalSection);

			TerminateThread(measure->threadHandle, 0);
			measure->threadHandle = nullptr;

			LeaveCriticalSection(&g_CriticalSection);
		}

		if (measure->dlThreadHandle)
		{
			// Thread is killed inside critical section so that itself is not inside one when it is terminated
			EnterCriticalSection(&g_CriticalSection);

			TerminateThread(measure->dlThreadHandle, 0);
			measure->dlThreadHandle = nullptr;

			LeaveCriticalSection(&g_CriticalSection);
		}

		measure->updateCounter = 0;
	}
	else if (_wcsicmp(args, L"RESET") == 0)
	{
		measure->resultString.clear();
		measure->downloadedFile.clear();

		EnterCriticalSection(&g_CriticalSection);

		// Update the references
		std::vector<MeasureData*>::iterator i = g_Measures.begin();
		std::wstring compareStr = L"[";
		compareStr += RmGetMeasureName(measure->rm);
		compareStr += L']';
		for (; i != g_Measures.end(); ++i)
		{
			if ((StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos) &&
				(measure->skin == (*i)->skin))
			{
				(*i)->resultString.clear();
				(*i)->downloadedFile.clear();
			}
		}
		LeaveCriticalSection(&g_CriticalSection);
	}
}
Пример #5
0
PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
	RmLog(LOG_DEBUG, L"RainFbx.dll: Initialize");

	FbxMeasureConf* measureConfig = new FbxMeasureConf;
	*data = measureConfig;
	void* skin = RmGetSkin(rm);

	LPCWSTR fbxAPIConf = RmReadString(rm, L"FbxAPIConf", L"");

	if (!*fbxAPIConf) {
		/* [FbxAPIConf] (parent) */
		RmLog(LOG_DEBUG, L"RainFbx.dll: Reading [FbxAPIConf] (parent)");
		measureConfig->fbxAPIConf = new FbxAPIConf;
		measureConfig->fbxAPIConf->section = RmGetMeasureName(rm);
		measureConfig->fbxAPIConf->skin = skin;
		measureConfig->fbxAPIConf->lastConfig = measureConfig;
		g_FbxAPIConfs.push_back(measureConfig->fbxAPIConf);
		fbx.app_token = RmReadString(rm, L"AppToken", L"");
		if(fbx.app_token == L"") writeAppToken = true;
		fbx.setHostname(RmReadString(rm, L"Hostname", L""));
	}
	else {
		/* [FbxMeasureConf] (child) */
		RmLog(LOG_DEBUG, L"RainFbx.dll: Reading [FbxMeasureConf] (child)");
		// Find parent using name AND the skin handle to be sure that it's the right one
		std::vector<FbxAPIConf*>::const_iterator iter = g_FbxAPIConfs.begin();
		for (; iter != g_FbxAPIConfs.end(); ++iter)	{
			if ( ( (*iter)->section == fbxAPIConf ) && ( (*iter)->skin == skin ) )	{
				measureConfig->section = RmGetMeasureName(rm);
				measureConfig->fbxAPIConf = (*iter);
				return;
			}
		}
		RmLog(LOG_ERROR, L"RainFbx.dll: Invalid FbxAPIConf=");
	}
}
Пример #6
0
PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
	MeasureData* measure = new MeasureData;
	*data = measure;
	g_Measures.push_back(measure);

	measure->skin = RmGetSkin(rm);
	measure->section = RmGetMeasureName(rm);

	if (g_InstanceCount == 0)
	{
		InitializeCriticalSection(&g_CriticalSection);
		FillCharacterEntityReferences();

		SetupGlobalProxySetting();
	}

	SetupProxySetting(measure->proxy, rm);  // No support for DynamicVariables

	++g_InstanceCount;
}
Пример #7
0
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	MeasureData* measure = (MeasureData*)data;

	LPCWSTR value = RmReadString(rm, L"RecycleType", L"COUNT");
	if (_wcsicmp(L"COUNT", value) == 0)
	{
		measure->count = true;
	}
	else if (_wcsicmp(L"SIZE", value) == 0)
	{
		measure->count = false;
	}
	else
	{
		WCHAR buffer[256];
		_snwprintf_s(buffer, _TRUNCATE, L"RecycleManager.dll: RecycleType=%s is not valid in [%s]", value, RmGetMeasureName(rm));
		RmLog(LOG_ERROR, buffer);
	}
}
Пример #8
0
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	MeasureData* measure = (MeasureData*)data;

	LPCWSTR type = RmReadString(rm, L"ResCountType", L"GDI");
	if (_wcsicmp(L"GDI", type) == 0)
	{
		measure->type = GDI_COUNT;
	}
	else if (_wcsicmp(L"USER", type) == 0)
	{
		measure->type = USER_COUNT;
	}
	else if (_wcsicmp(L"HANDLE", type) == 0)
	{
		measure->type = HANDLE_COUNT;
	}
	else if (_wcsicmp(L"WINDOW", type) == 0)
	{
		measure->type = WINDOW_COUNT;
	}
	else
	{
		WCHAR buffer[256];
		_snwprintf_s(buffer, _TRUNCATE, L"ResMon.dll: GDICountType=%s is not valid in [%s]", type, RmGetMeasureName(rm));
		RmLog(LOG_ERROR, buffer);
	}

	measure->process = RmReadString(rm, L"ProcessName", L"");
}
Пример #9
0
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	MeasureData* measure = (MeasureData*)data;

	int defaultData = -1;

	LPCTSTR type = RmReadString(rm, L"SysInfoType", L"");
	if (_wcsicmp(L"COMPUTER_NAME", type) == 0)
	{
		measure->type = MEASURE_COMPUTER_NAME;
	}
	else if (_wcsicmp(L"USER_NAME", type) == 0)
	{
		measure->type = MEASURE_USER_NAME;
	}
	else if (_wcsicmp(L"WORK_AREA", type) == 0)
	{
		measure->type = MEASURE_WORK_AREA;
	}
	else if (_wcsicmp(L"SCREEN_SIZE", type) == 0)
	{
		measure->type = MEASURE_SCREEN_SIZE;
	}
	else if (_wcsicmp(L"RAS_STATUS", type) == 0)
	{
		measure->type = MEASURE_RAS_STATUS;
	}
	else if (_wcsicmp(L"OS_VERSION", type) == 0)
	{
		measure->type = MEASURE_OS_VERSION;
	}
	else if (_wcsicmp(L"OS_BITS", type) == 0)
	{
		measure->type = MEASURE_OS_BITS;
	}
	else if (_wcsicmp(L"ADAPTER_DESCRIPTION", type) == 0)
	{
		defaultData = 0;
		measure->type = MEASURE_ADAPTER_DESCRIPTION;
	}
	else if (_wcsicmp(L"NET_MASK", type) == 0)
	{
		defaultData = 0;
		measure->type = MEASURE_NET_MASK;
	}
	else if (_wcsicmp(L"IP_ADDRESS", type) == 0)
	{
		defaultData = 0;
		measure->type = MEASURE_IP_ADDRESS;
	}
	else if (_wcsicmp(L"GATEWAY_ADDRESS", type) == 0)
	{
		defaultData = 0;
		measure->type = MEASURE_GATEWAY_ADDRESS;
	}
	else if (_wcsicmp(L"HOST_NAME", type) == 0)
	{
		measure->type = MEASURE_HOST_NAME;
	}
	else if (_wcsicmp(L"DOMAIN_NAME", type) == 0)
	{
		measure->type = MEASURE_DOMAIN_NAME;
	}
	else if (_wcsicmp(L"DNS_SERVER", type) == 0)
	{
		measure->type = MEASURE_DNS_SERVER;
	}
	else if (_wcsicmp(L"WORK_AREA_TOP", type) == 0)
	{
		measure->type = MEASURE_WORK_AREA_TOP;
	}
	else if (_wcsicmp(L"WORK_AREA_LEFT", type) == 0)
	{
		measure->type = MEASURE_WORK_AREA_LEFT;
	}
	else if (_wcsicmp(L"WORK_AREA_WIDTH", type) == 0)
	{
		measure->type = MEASURE_WORK_AREA_WIDTH;
	}
	else if (_wcsicmp(L"WORK_AREA_HEIGHT", type) == 0)
	{
		measure->type = MEASURE_WORK_AREA_HEIGHT;
	}
	else if (_wcsicmp(L"SCREEN_WIDTH", type) == 0)
	{
		measure->type = MEASURE_SCREEN_WIDTH;
	}
	else if (_wcsicmp(L"SCREEN_HEIGHT", type) == 0)
	{
		measure->type = MEASURE_SCREEN_HEIGHT;
	}
	else if (_wcsicmp(L"NUM_MONITORS", type) == 0)
	{
		measure->type = MEASURE_NUM_MONITORS;
	}
	else if (_wcsicmp(L"VIRTUAL_SCREEN_TOP", type) == 0)
	{
		measure->type = MEASURE_VIRTUAL_SCREEN_TOP;
	}
	else if (_wcsicmp(L"VIRTUAL_SCREEN_LEFT", type) == 0)
	{
		measure->type = MEASURE_VIRTUAL_SCREEN_LEFT;
	}
	else if (_wcsicmp(L"VIRTUAL_SCREEN_WIDTH", type) == 0)
	{
		measure->type = MEASURE_VIRTUAL_SCREEN_WIDTH;
	}
	else if (_wcsicmp(L"VIRTUAL_SCREEN_HEIGHT", type) == 0)
	{
		measure->type = MEASURE_VIRTUAL_SCREEN_HEIGHT;
	}
	else
	{
		WCHAR buffer[256];
		_snwprintf_s(buffer, _TRUNCATE, L"SysInfo.dll: SysInfoType=%s is not valid in [%s]", type, RmGetMeasureName(rm));
		RmLog(LOG_ERROR, buffer);
	}

	measure->data = RmReadInt(rm, L"SysInfoData", defaultData);
}
Пример #10
0
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	Measure* measure = (Measure*)data;
	measure->rm = rm;
	
	//初始化 PlayerName
	LPCWSTR str = RmReadString(rm, L"PlayerName", L"");

	if (!_wcsicmp(L"KwMusic", str))
	{
		measure->name = PLAYER_KUWO;
		measure->player = KwMusic::Create();
	}
	else if (!_wcsicmp(L"KgMusic", str))
	{
		measure->name = PLAYER_KUGOU;
		measure->player = KgMusic::Create();
	}
	else if (!_wcsicmp(L"QQMusic", str))
	{
		measure->name = PLAYER_QQ;
		measure->player = QQMusic::Create();
	}
	else if (!_wcsicmp(L"BaiduMusic", str))
	{
		measure->name = PLAYER_BAIDU;
		measure->player = BaiduMusic::Create();
	}
	else
	{

		measure->name = PLAYER_KUWO;
		measure->player = KwMusic::Create();

		wstring error = L"MusicPlayer.dll: Invalid PlayerName=";
		error += str;
		error += L" in [";
		error += RmGetMeasureName(rm);
		error += L"]";
		RmLog(LOG_WARNING, error.c_str());
	}



	//初始化 PlayerType
	str = RmReadString(rm, L"PlayerType", L"");

	if (_wcsicmp(L"TITLE", str) == 0)
	{
		measure->type = MEASURE_TITLE;
	}
	else if (_wcsicmp(L"ARTIST", str) == 0)
	{
		measure->type = MEASURE_ARTIST;
	}
	else if (_wcsicmp(L"TRACK", str) == 0)
	{
		measure->type = MEASURE_TRACK;
	}
	else if (_wcsicmp(L"PLAYERPATH", str) == 0)
	{
		measure->type = MEASURE_PLAYERPATH;
		measure->playerpath = RmReadString(rm, L"PlayerPath", L"");
	}
	else if (_wcsicmp(L"STATUS", str) == 0)
	{
		measure->type = MEASURE_STATUS;
	}
	else if (_wcsicmp(L"COVER", str) == 0)
	{
		measure->type = MEASURE_COVER;
		switch (measure->name)
		{
		case PLAYER_KUGOU:
		case PLAYER_QQ:
			measure->player->m_RequireCover = true;
		}
	}
	else
	{
		std::wstring error = L"MusicPlayer.dll: Invalid PlayerType=";
		error += str;
		error += L" in [";
		error += RmGetMeasureName(rm);
		error += L"]";
		RmLog(LOG_WARNING, error.c_str());
	}

	measure->trackChangeAction = RmReadString(rm, L"TrackChangeAction", L"");

}
Пример #11
0
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	MeasureData* measure = (MeasureData*)data;

	LPCWSTR type =  RmReadString(rm, L"SpeedFanType", L"TEMPERATURE");
	if (_wcsicmp(L"TEMPERATURE", type) == 0)
	{
		measure->type = TYPE_TEMP;

		LPCWSTR scale = RmReadString(rm, L"SpeedFanScale", L"C");
		if (_wcsicmp(L"C", scale) == 0)
		{
			measure->scale = SCALE_CENTIGRADE;
		}
		else if (_wcsicmp(L"F", scale) == 0)
		{
			measure->scale = SCALE_FARENHEIT;
		}
		else if (_wcsicmp(L"K", scale) == 0)
		{
			measure->scale = SCALE_KELVIN;
		}
		else
		{
			WCHAR buffer[256];
			_snwprintf_s(buffer, _TRUNCATE, L"SpeedFanPlugin.dll: SpeedFanScale=%s is not valid in [%s]", scale, RmGetMeasureName(rm));
			RmLog(LOG_ERROR, buffer);
		}
	}
	else if (_wcsicmp(L"FAN", type) == 0)
	{
		measure->type = TYPE_FAN;
	}
	else if (_wcsicmp(L"VOLTAGE", type) == 0)
	{
		measure->type = TYPE_VOLT;
	}
	else
	{
		WCHAR buffer[256];
		_snwprintf_s(buffer, _TRUNCATE, L"SpeedFanPlugin.dll: SpeedFanType=%s is not valid in [%s]", type, RmGetMeasureName(rm));
		RmLog(LOG_ERROR, buffer);
	}

	measure->number = RmReadInt(rm, L"SpeedFanNumber", 0);
}
Пример #12
0
PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	Measure* measure = (Measure*)data;

	// Data is stored in two structs: Measure and ParentMeasure. ParentMeasure is created for measures
	// with PlayerName=someplayer. Measure is created for all measures and points to ParentMeasure as
	// referenced in PlayerName=[section].

	// Read settings from the ini-file
	void* skin = RmGetSkin(rm);
	LPCWSTR str = RmReadString(rm, L"PlayerName", L"", FALSE);
	if (str[0] == L'[')
	{
		if (measure->parent)
		{
			// Don't let a measure measure change its parent
		}
		else
		{
			// PlayerName starts with [ so use referenced section
			++str;
			size_t len = wcslen(str);
			if (len > 0 && str[len - 1] == L']')
			{
				--len;

				std::vector<ParentMeasure*>::iterator iter = g_ParentMeasures.begin();
				for ( ; iter != g_ParentMeasures.end(); ++iter)
				{
					if (skin == (*iter)->skin &&
						_wcsnicmp(str, (*iter)->ownerName, len) == 0)
					{
						// Use same ParentMeasure as referenced section
						measure->parent = (*iter);
						++measure->parent->measureCount;

						break;
					}
				}

				if (!measure->parent)
				{
					// The referenced section doesn't exist
					std::wstring error = L"NowPlaying.dll: Invalid PlayerName=";
					error.append(str - 1, len + 2);
					error += L" in [";
					error += RmGetMeasureName(rm);
					error += L"]";
					RmLog(LOG_WARNING, error.c_str());
					return;
				}
			}
		}
	}
	else
	{
		// ParentMeasure is created when PlayerName is an actual player (and not a reference)
		ParentMeasure* parent = measure->parent;
		Player* oldPlayer = nullptr;
		if (parent)
		{
			if (parent->data != data)
			{
				// Don't let a measure-only measure become a parent measure
				return;
			}

			oldPlayer = parent->player;
		}
		else
		{
			parent = new ParentMeasure;
			g_ParentMeasures.push_back(parent);
			parent->data = data;
			parent->skin = skin;
			parent->ownerName = RmGetMeasureName(rm);
			measure->parent = parent;
		}

		if (_wcsicmp(L"AIMP", str) == 0)
		{
			parent->player = PlayerAIMP::Create();
		}
		else if (_wcsicmp(L"CAD", str) == 0)
		{
			parent->player = PlayerCAD::Create();
		}
		else if (_wcsicmp(L"foobar2000", str) == 0)
		{
			HWND fooWindow = FindWindow(L"foo_rainmeter_class", nullptr);
			if (fooWindow)
			{
				const WCHAR* error = L"Your foobar2000 plugin is out of date.\n\nDo you want to update the plugin now?";
				if (MessageBox(nullptr, error, L"Rainmeter", MB_YESNO | MB_ICONINFORMATION | MB_TOPMOST) == IDYES)
				{
					ShellExecute(nullptr, L"open", L"http://github.com/poiru/foo-cad#readme", nullptr, nullptr, SW_SHOWNORMAL);
				}
			}

			parent->player = PlayerCAD::Create();
		}
		else if (_wcsicmp(L"iTunes", str) == 0)
		{
			parent->player = PlayerITunes::Create();
		}
		else if (_wcsicmp(L"MediaMonkey", str) == 0)
		{
			parent->player = PlayerWinamp::Create(WA_MEDIAMONKEY);
		}
		else if (_wcsicmp(L"Spotify", str) == 0)
		{
			parent->player = PlayerSpotify::Create();
		}
		else if (_wcsicmp(L"WinAmp", str) == 0)
		{
			parent->player = PlayerWinamp::Create(WA_WINAMP);
		}
		else if (_wcsicmp(L"WMP", str) == 0)
		{
			parent->player = PlayerWMP::Create();
		}
		else
		{
			// Default to WLM
			parent->player = PlayerWLM::Create();

			if (_wcsicmp(L"WLM", str) != 0)
			{
				std::wstring error = L"NowPlaying.dll: Invalid PlayerName=";
				error += str;
				error += L" in [";
				error += parent->ownerName;
				error += L"]";
				RmLog(LOG_ERROR, error.c_str());
			}
		}

		parent->player->AddInstance();
		parent->playerPath = RmReadString(rm, L"PlayerPath", L"");
		parent->trackChangeAction = RmReadString(rm, L"TrackChangeAction", L"", FALSE);
		parent->disableLeadingZero = RmReadInt(rm, L"DisableLeadingZero", 0) != 0;

		if (oldPlayer)
		{
			parent->player->SetMeasures(oldPlayer->GetMeasures());

			// Remove instance here so that player doesn't have to reinitialize if PlayerName was
			// not changed.
			oldPlayer->RemoveInstance();
		}
	}

	str = RmReadString(rm, L"PlayerType", L"");
	if (_wcsicmp(L"ARTIST", str) == 0)
	{
		measure->type = MEASURE_ARTIST;
	}
	else if (_wcsicmp(L"TITLE", str) == 0)
	{
		measure->type = MEASURE_TITLE;
	}
	else if (_wcsicmp(L"ALBUM", str) == 0)
	{
		measure->type = MEASURE_ALBUM;
	}
	else if (_wcsicmp(L"COVER", str) == 0)
	{
		measure->type = MEASURE_COVER;
	}
	else if (_wcsicmp(L"DURATION", str) == 0)
	{
		measure->type = MEASURE_DURATION;
	}
	else if (_wcsicmp(L"POSITION", str) == 0)
	{
		measure->type = MEASURE_POSITION;
	}
	else if (_wcsicmp(L"PROGRESS", str) == 0)
	{
		measure->type = MEASURE_PROGRESS;
		*maxValue = 100.0;
	}
	else if (_wcsicmp(L"RATING", str) == 0)
	{
		measure->type = MEASURE_RATING;
		*maxValue = 5.0;
	}
	else if (_wcsicmp(L"STATE", str) == 0)
	{
		measure->type = MEASURE_STATE;
	}
	else if (_wcsicmp(L"STATUS", str) == 0)
	{
		measure->type = MEASURE_STATUS;
	}
	else if (_wcsicmp(L"VOLUME", str) == 0)
	{
		measure->type = MEASURE_VOLUME;
		*maxValue = 100.0;
	}
	else if (_wcsicmp(L"SHUFFLE", str) == 0)
	{
		measure->type = MEASURE_SHUFFLE;
	}
	else if (_wcsicmp(L"REPEAT", str) == 0)
	{
		measure->type = MEASURE_REPEAT;
	}
	else if (_wcsicmp(L"LYRICS", str) == 0)
	{
		RmLog(LOG_WARNING, L"NowPlaying.dll: Using undocumented PlayerType=LYRICS!");
		measure->type = MEASURE_LYRICS;
	}
	else if (_wcsicmp(L"FILE", str) == 0)
	{
		measure->type = MEASURE_FILE;
	}
	else if (_wcsicmp(L"NUMBER", str) == 0)
	{
		measure->type = MEASURE_NUMBER;
	}
	else if (_wcsicmp(L"YEAR", str) == 0)
	{
		measure->type = MEASURE_YEAR;
	}
	else
	{
		std::wstring error = L"NowPlaying.dll: Invalid PlayerType=";
		error += str;
		error += L" in [";
		error += RmGetMeasureName(rm);
		error += L"]";
		RmLog(LOG_WARNING, error.c_str());
	}

	measure->parent->player->AddMeasure(measure->type);
}
Пример #13
0
void ParseData(MeasureData* measure, const BYTE* rawData, DWORD rawSize, bool utf16Data)
{
	const int UTF16_CODEPAGE = 1200;
	if (measure->codepage == UTF16_CODEPAGE) {
		utf16Data = true;
	}

	const char* error;
	int erroffset;
	int ovector[OVECCOUNT];
	int rc;
	bool doErrorAction = false;

	// Compile the regular expression in the first argument
	pcre16* re = pcre16_compile(
		(PCRE_SPTR16)measure->regExp.c_str(),
		PCRE_UTF16, &error, &erroffset, nullptr);
	if (re != nullptr)
	{
		// Compilation succeeded: match the subject in the second argument
		std::wstring buffer;
		auto data = (const WCHAR*)rawData;
		DWORD dataLength = rawSize / 2;
		if (!utf16Data)
		{
			buffer = StringUtil::Widen((LPCSTR)rawData, rawSize, measure->codepage);
			data = buffer.c_str();
			dataLength = (DWORD)buffer.length();
		}

		rc = pcre16_exec(re, nullptr, (PCRE_SPTR16)data, dataLength, 0, 0, ovector, OVECCOUNT);
		if (rc >= 0)
		{
			if (rc == 0)
			{
				// The output vector wasn't big enough
				RmLog(measure->rm, LOG_ERROR, L"WebParser: Too many substrings");
			}
			else
			{
				if (measure->stringIndex < rc)
				{
					if (measure->debug != 0)
					{
						for (int i = 0; i < rc; ++i)
						{
							const WCHAR* match = data + ovector[2 * i];
							const int matchLen = min(ovector[2 * i + 1] - ovector[2 * i], 256);
							RmLogF(measure->rm, LOG_DEBUG, L"WebParser: Index %2d: %.*s", i, matchLen, match);
						}
					}

					const WCHAR* match = data + ovector[2 * measure->stringIndex];
					int matchLen = ovector[2 * measure->stringIndex + 1] - ovector[2 * measure->stringIndex];
					EnterCriticalSection(&g_CriticalSection);
					measure->resultString.assign(match, matchLen);
					DecodeReferences(measure->resultString, measure->decodeCharacterReference);
					LeaveCriticalSection(&g_CriticalSection);
				}
				else
				{
					RmLog(measure->rm, LOG_WARNING, L"WebParser: Not enough substrings");

					// Clear the old result
					EnterCriticalSection(&g_CriticalSection);
					measure->resultString.clear();
					if (measure->download)
					{
						if (measure->downloadFile.empty())  // cache mode
						{
							if (!measure->downloadedFile.empty())
							{
								// Delete old downloaded file
								DeleteFile(measure->downloadedFile.c_str());
							}
						}
						measure->downloadedFile.clear();
					}
					LeaveCriticalSection(&g_CriticalSection);
				}

				// Update the references
				std::vector<MeasureData*>::iterator i = g_Measures.begin();
				std::wstring compareStr = L"[";
				compareStr += RmGetMeasureName(measure->rm);
				compareStr += L']';
				for ( ; i != g_Measures.end(); ++i)
				{
					if (measure->skin == (*i)->skin &&
						StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos)
					{
						if ((*i)->stringIndex < rc)
						{
							const WCHAR* match = data + ovector[2 * (*i)->stringIndex];
							int matchLen = ovector[2 * (*i)->stringIndex + 1] - ovector[2 * (*i)->stringIndex];
							if (!(*i)->regExp.empty())
							{
								// Change the index and parse the substring
								int index = (*i)->stringIndex;
								(*i)->stringIndex = (*i)->stringIndex2;
								ParseData((*i), (BYTE*)match, matchLen * 2, true);
								(*i)->stringIndex = index;
							}
							else
							{
								// Set the result
								EnterCriticalSection(&g_CriticalSection);

								// Substitude the [measure] with result
								(*i)->resultString = (*i)->url;
								(*i)->resultString.replace(
									StringUtil::CaseInsensitiveFind((*i)->resultString, compareStr),
									compareStr.size(), match, matchLen);
								DecodeReferences((*i)->resultString, (*i)->decodeCharacterReference);

								// Start download threads for the references
								if ((*i)->download)
								{
									// Start the download thread
									unsigned int id;
									HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, (*i), 0, &id);
									if (threadHandle)
									{
										(*i)->dlThreadHandle = threadHandle;
									}
								}

								LeaveCriticalSection(&g_CriticalSection);
							}
						}
						else
						{
							RmLog((*i)->rm, LOG_WARNING, L"WebParser: Not enough substrings");

							// Clear the old result
							EnterCriticalSection(&g_CriticalSection);
							(*i)->resultString.clear();
							if ((*i)->download)
							{
								if ((*i)->downloadFile.empty())  // cache mode
								{
									if (!(*i)->downloadedFile.empty())
									{
										// Delete old downloaded file
										DeleteFile((*i)->downloadedFile.c_str());
									}
								}
								(*i)->downloadedFile.clear();
							}
							LeaveCriticalSection(&g_CriticalSection);
						}
					}
				}
			}
		}
		else
		{
			// Matching failed: handle error cases
			RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp matching error (%d)", rc);
			doErrorAction = true;

			EnterCriticalSection(&g_CriticalSection);
			measure->resultString = measure->errorString;

			// Update the references
			std::vector<MeasureData*>::iterator i = g_Measures.begin();
			std::wstring compareStr = L"[";
			compareStr += RmGetMeasureName(measure->rm);
			compareStr += L']';
			for ( ; i != g_Measures.end(); ++i)
			{
				if ((StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos) &&
					(measure->skin == (*i)->skin))
				{
					(*i)->resultString = (*i)->errorString;
				}
			}
			LeaveCriticalSection(&g_CriticalSection);
		}

		// Release memory used for the compiled pattern
		pcre16_free(re);
	}
	else
	{
		// Compilation failed.
		RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp error at offset %d: %S", erroffset, error);
		doErrorAction = true;
	}

	if (measure->download)
	{
		// Start the download thread
		unsigned int id;
		HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, measure, 0, &id);
		if (threadHandle)
		{
			measure->dlThreadHandle = threadHandle;
		}
	}

	if (doErrorAction && !measure->onRegExpErrAction.empty())
	{
		RmExecute(measure->skin, measure->onRegExpErrAction.c_str());
	}
	else if (!measure->download && !measure->finishAction.empty())
	{
		RmExecute(measure->skin, measure->finishAction.c_str());
	}
}
Пример #14
0
void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize)
{
	// Parse the value from the data
	pcre* re;
	const char* error;
	int erroffset;
	int ovector[OVECCOUNT];
	int rc;
	int flags = PCRE_UTF8;

	if (measure->codepage == 0)
	{
		flags = 0;
	}

	// Compile the regular expression in the first argument
	re = pcre_compile(
		StringUtil::NarrowUTF8(measure->regExp).c_str(),	// the pattern
		flags,												// default options
		&error,												// for error message
		&erroffset,											// for error offset
		nullptr);											// use default character tables

	if (re != nullptr)
	{
		// Compilation succeeded: match the subject in the second argument
		std::string utf8Data;

		if (measure->codepage == 1200)		// 1200 = UTF-16LE
		{
			// Must convert the data to utf8
			utf8Data = StringUtil::NarrowUTF8((LPCWSTR)parseData, dwSize / 2);
			parseData = utf8Data.c_str();
			dwSize = (DWORD)utf8Data.length();
		}
		else if (measure->codepage != CP_UTF8 && measure->codepage != 0)		// 0 = CP_ACP
		{
			// Must convert the data to utf8
			utf8Data = ConvertAsciiToUTF8(parseData, dwSize, measure->codepage);
			parseData = utf8Data.c_str();
			dwSize = (DWORD)utf8Data.length();
		}

		rc = pcre_exec(
			re,						// the compiled pattern
			nullptr,				// 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

		if (rc >= 0)
		{
			if (rc == 0)
			{
				// The output vector wasn't big enough
				RmLog(measure->rm, LOG_ERROR, L"WebParser: Too many substrings");
			}
			else
			{
				if (measure->stringIndex < rc)
				{
					if (measure->debug != 0)
					{
						for (int i = 0; i < rc; ++i)
						{
							const char* substring_start = parseData + ovector[2 * i];
							int substring_length = ovector[2 * i + 1] - ovector[2 * i];
							substring_length = min(substring_length, 256);

							const std::wstring value = StringUtil::WidenUTF8(substring_start, substring_length);
							RmLogF(measure->rm, LOG_DEBUG, L"WebParser: Index %2d: %s", i, value.c_str());
						}
					}

					const char* substring_start = parseData + ovector[2 * measure->stringIndex];
					int substring_length = ovector[2 * measure->stringIndex + 1] - ovector[2 * measure->stringIndex];

					EnterCriticalSection(&g_CriticalSection);
					measure->resultString = StringUtil::WidenUTF8(substring_start, substring_length);
					DecodeReferences(measure->resultString, measure->decodeCharacterReference);
					LeaveCriticalSection(&g_CriticalSection);
				}
				else
				{
					RmLog(measure->rm, LOG_WARNING, L"WebParser: Not enough substrings");

					// Clear the old result
					EnterCriticalSection(&g_CriticalSection);
					measure->resultString.clear();
					if (measure->download)
					{
						if (measure->downloadFile.empty())  // cache mode
						{
							if (!measure->downloadedFile.empty())
							{
								// Delete old downloaded file
								DeleteFile(measure->downloadedFile.c_str());
							}
						}
						measure->downloadedFile.clear();
					}
					LeaveCriticalSection(&g_CriticalSection);
				}

				// Update the references
				std::vector<MeasureData*>::iterator i = g_Measures.begin();
				std::wstring compareStr = L"[";
				compareStr += RmGetMeasureName(measure->rm);
				compareStr += L']';
				for ( ; i != g_Measures.end(); ++i)
				{
					if (measure->skin == (*i)->skin &&
						(*i)->url.find(compareStr) != std::wstring::npos)
					{
						if ((*i)->stringIndex < rc)
						{
							const char* substring_start = parseData + ovector[2 * (*i)->stringIndex];
							int substring_length = ovector[2 * (*i)->stringIndex + 1] - ovector[2 * (*i)->stringIndex];

							if (!(*i)->regExp.empty())
							{
								// Change the index and parse the substring
								int index = (*i)->stringIndex;
								(*i)->stringIndex = (*i)->stringIndex2;
								ParseData((*i), substring_start, substring_length);
								(*i)->stringIndex = index;
							}
							else
							{
								// Set the result
								EnterCriticalSection(&g_CriticalSection);

								// Substitude the [measure] with result
								std::wstring result = StringUtil::WidenUTF8(substring_start, substring_length);
								(*i)->resultString = (*i)->url;
								(*i)->resultString.replace((*i)->resultString.find(compareStr), compareStr.size(), result);
								DecodeReferences((*i)->resultString, (*i)->decodeCharacterReference);

								// Start download threads for the references
								if ((*i)->download)
								{
									// Start the download thread
									unsigned int id;
									HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, (*i), 0, &id);
									if (threadHandle)
									{
										(*i)->dlThreadHandle = threadHandle;
									}
								}

								LeaveCriticalSection(&g_CriticalSection);
							}
						}
						else
						{
							RmLog((*i)->rm, LOG_WARNING, L"WebParser: Not enough substrings");

							// Clear the old result
							EnterCriticalSection(&g_CriticalSection);
							(*i)->resultString.clear();
							if ((*i)->download)
							{
								if ((*i)->downloadFile.empty())  // cache mode
								{
									if (!(*i)->downloadedFile.empty())
									{
										// Delete old downloaded file
										DeleteFile((*i)->downloadedFile.c_str());
									}
								}
								(*i)->downloadedFile.clear();
							}
							LeaveCriticalSection(&g_CriticalSection);
						}
					}
				}
			}
		}
		else
		{
			// Matching failed: handle error cases
			RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp matching error (%d)", rc);

			EnterCriticalSection(&g_CriticalSection);
			measure->resultString = measure->errorString;

			// Update the references
			std::vector<MeasureData*>::iterator i = g_Measures.begin();
			std::wstring compareStr = L"[";
			compareStr += RmGetMeasureName(measure->rm);
			compareStr += L']';
			for ( ; i != g_Measures.end(); ++i)
			{
				if (((*i)->url.find(compareStr) != std::wstring::npos) && (measure->skin == (*i)->skin))
				{
					(*i)->resultString = (*i)->errorString;
				}
			}
			LeaveCriticalSection(&g_CriticalSection);
		}

		// Release memory used for the compiled pattern
		pcre_free(re);
	}
	else
	{
		// Compilation failed.
		RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp error at offset %d: %S", erroffset, error);
	}

	if (measure->download)
	{
		// Start the download thread
		unsigned int id;
		HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, measure, 0, &id);
		if (threadHandle)
		{
			measure->dlThreadHandle = threadHandle;
		}
	}
	else
	{
		if (!measure->finishAction.empty())
		{
			RmExecute(measure->skin, measure->finishAction.c_str());
		}
	}
}