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="); } }
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; }
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); }
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); } }
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="); } }
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; }
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); } }
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""); }
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); }
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""); }
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); }
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); }
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()); } }
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()); } } }