diff options
author | George Hazan <ghazan@miranda.im> | 2019-03-02 12:32:44 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-03-02 12:32:55 +0300 |
commit | 931a7dc1ac0dbc7e6c1083583ced915e572f5b47 (patch) | |
tree | 9fe9a6448d44030e26aa7107ce16044ed413e0d0 /protocols/Weather/src/weather_ini.cpp | |
parent | dd7d9954042254e66e3bbbec7195c6be8b1a0663 (diff) |
all protocols (even virtual ones) moved to the Protocols folder
Diffstat (limited to 'protocols/Weather/src/weather_ini.cpp')
-rw-r--r-- | protocols/Weather/src/weather_ini.cpp | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/protocols/Weather/src/weather_ini.cpp b/protocols/Weather/src/weather_ini.cpp new file mode 100644 index 0000000000..000eab1bc9 --- /dev/null +++ b/protocols/Weather/src/weather_ini.cpp @@ -0,0 +1,592 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (c) 2012 Miranda NG team +Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (c) 2002-2005 Calvin Che + +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; version 2 +of the License. + +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, see <http://www.gnu.org/licenses/>. +*/ + + +/* +This file contain the source related to loading the reading the +weather ini files and store them into memory. Also containing +code for unloading and getting weather data from the ini settings. +*/ + +#include "stdafx.h" + +HWND hWndSetup; + +//============ DATA LIST (LINKED LIST) ============ +// +// add an item into weather service data list +// Data = the service data to be added to the list +static void WIListAdd(WIDATA Data) +{ + // create a new datalist item and point to the data + WIDATALIST *newItem = (WIDATALIST*)mir_alloc(sizeof(WIDATALIST)); + newItem->Data = Data; + // add to the linked list + newItem->next = nullptr; + if (WITail == nullptr) WIHead = newItem; + else WITail->next = newItem; + WITail = newItem; +} + +// get the service data (from loaded ini file) by internal name +// pszServ = internal name for the service +// return value = the matching WIDATA struct for pszServ, NULL if no match found +WIDATA* GetWIData(wchar_t *pszServ) +{ + // loop through the list to find matching internal name + for (WIDATALIST *Item = WIHead; Item != nullptr; Item = Item->next) + // if internal name found, return the data + if (mir_wstrcmp(Item->Data.InternalName, pszServ) == 0) + return &Item->Data; + + // return NULL when no match found + return nullptr; +} + +//============ DATA ITEM LIST (LINKED LIST) ============ +// +// add a new update item into the current list +void WIItemListAdd(WIDATAITEM *DataItem, WIDATA *Data) +{ + WIDATAITEMLIST *newItem = (WIDATAITEMLIST*)mir_alloc(sizeof(WIDATAITEMLIST)); + newItem->Item = *DataItem; + newItem->Next = nullptr; + if (Data->UpdateData == nullptr) Data->UpdateData = newItem; + else Data->UpdateDataTail->Next = newItem; + Data->UpdateDataTail = newItem; +} + +// reset the data item by using empty string +// Item = the item to set +// name = the string to store in the "name" field +void ResetDataItem(WIDATAITEM *Item, const wchar_t *name) +{ + Item->Name = mir_wstrdup(name); + Item->Start = L""; + Item->End = L""; + Item->Unit = L""; + Item->Url = ""; + Item->Break = L""; + Item->Type = 0; +} + +// free the data item by using empty string +// Item = the item to free +void FreeDataItem(WIDATAITEM *Item) +{ + wfree(&Item->Name); + wfree(&Item->Start); + wfree(&Item->End); + wfree(&Item->Unit); + wfree(&Item->Url); + wfree(&Item->Break); +} + +//============ Condition Icon List ============ +// +// initiate icon assignmet list +void WICondListInit(WICONDLIST *List) +{ + List->Tail = nullptr; + List->Head = nullptr; +} + +// add a new update item into the current list +void WICondListAdd(char *str, WICONDLIST *List) +{ + WICONDITEM *newItem = (WICONDITEM*)mir_alloc(sizeof(WICONDITEM)); + wSetData(&newItem->Item, str); + CharLowerBuff(newItem->Item, (DWORD)mir_wstrlen(newItem->Item)); + newItem->Next = nullptr; + if (List->Tail == nullptr) List->Head = newItem; + else List->Tail->Next = newItem; + List->Tail = newItem; +} + +// check if the condition string matched for the assignment +bool IsContainedInCondList(const wchar_t *pszStr, WICONDLIST *List) +{ + // loop through the list to find matching internal name + for (WICONDITEM *Item = List->Head; Item != nullptr; Item = Item->Next) { + // if internal name found, return true indicating that the data is found + if (wcsstr(pszStr, Item->Item)) + return true; + + } + // return false when no match found + return false; +} + +// free the memory for icon assignment list +void DestroyCondList(WICONDLIST *List) +{ + // free the list one by one + for (WICONDITEM *temp = List->Head; temp != nullptr; temp = List->Head) { + List->Head = temp->Next; + wfree(&temp->Item); // free the data struct + mir_free(temp); + } + // make sure the entire list is clear + List->Tail = nullptr; +} + + +//============ WEATHER INI SETUP DIALOG ============ +// +static INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + // make the buttons flat + SendDlgItemMessage(hwndDlg, IDC_STEP1, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_STEP2, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_STEP3, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_STEP4, BUTTONSETASFLATBTN, TRUE, 0); + + // set icons + Window_SetIcon_IcoLib(hwndDlg, GetIconHandle("main")); + + WindowList_Add(hWindowList, hwndDlg); + ShowWindow(hwndDlg, SW_SHOW); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_STEP1: + // update current data + Utils_OpenUrl("https://miranda-ng.org/"); + break; + + case IDC_STEP2: + { + wchar_t szPath[1024]; + GetModuleFileName(GetModuleHandle(nullptr), szPath, _countof(szPath)); + wchar_t *chop = wcsrchr(szPath, '\\'); + if (chop) { + *chop = '\0'; + mir_wstrncat(szPath, L"\\Plugins\\weather\\", _countof(szPath) - mir_wstrlen(szPath)); + if (_wmkdir(szPath) == 0) + ShellExecute((HWND)lParam, L"open", szPath, L"", L"", SW_SHOW); + } + break; + } + + case IDC_STEP3: + if (LoadWIData(false)) + MessageBox(nullptr, + TranslateT("All update data has been reloaded."), + TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); + break; + + case IDC_STEP4: + WeatherAdd(0, 0); + __fallthrough; + + case IDCANCEL: + // close the info window + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + Window_FreeIcon_IcoLib(hwndDlg); + break; + } + return FALSE; +} + +// load the station data from a file +// pszFile = the file name + path for the ini file to be loaded +// pszShortFile = the file name of the ini file, but not including the path +// Data = the struct to load the ini content to, and return to previous function +static void LoadStationData(wchar_t *pszFile, wchar_t *pszShortFile, WIDATA *Data) +{ + WIDATAITEM DataItem; + char *Group, *Temp; + char *ValName, *Value; + + static const char *statusStr[10] = + { + "LIGHTNING", + "FOG", + "SNOW SHOWER", + "SNOW", + "RAIN SHOWER", + "RAIN", + "PARTLY CLOUDY", + "CLOUDY", + "SUNNY", + "N/A" + }; + + // clean up old stuff + memset(Data, 0, sizeof(*Data)); + Data->Enabled = FALSE; + + // open the ini file + FILE *pfile = _wfsopen(pszFile, L"rt", _SH_DENYWR); + if (pfile != nullptr) { + char Line[4096]; + fgets(Line, _countof(Line), pfile); + TrimString(Line); + + // make sure it is a valid weather protocol ini file + if (!mir_strcmp(Line, "[Weather 0.3.x Update Data]")) + Data->InternalVer = 1; + else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.1]")) + Data->InternalVer = 2; + else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.1a]")) + Data->InternalVer = 3; + else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.2]")) + Data->InternalVer = 4; + else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.3]")) + Data->InternalVer = 5; + else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.4]")) + Data->InternalVer = 6; + else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.5]")) + Data->InternalVer = 7; + else { + wchar_t str[4096]; + mir_snwprintf(str, TranslateT("Invalid ini format for: %s"), pszFile); + MessageBox(nullptr, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONERROR); + fclose(pfile); + return; + } + + // initialize all data fields + Group = ""; + + Data->DisplayName = L""; + Data->InternalName = L""; + Data->Description = L""; + Data->Author = L""; + Data->Version = L""; + Data->DefaultURL = ""; + Data->DefaultMap = L""; + Data->UpdateURL = ""; + Data->UpdateURL2 = ""; + Data->UpdateURL3 = ""; + Data->UpdateURL4 = ""; + Data->Cookie = ""; + Data->UserAgent = ""; + Data->IDSearch.SearchURL = ""; + Data->IDSearch.NotFoundStr = L""; + Data->NameSearch.SearchURL = ""; + Data->NameSearch.NotFoundStr = L""; + Data->NameSearch.SingleStr = L""; + Data->NameSearch.Single.First = L""; + Data->NameSearch.Multiple.First = L""; + Data->IDSearch.Available = FALSE; + Data->NameSearch.Single.Available = FALSE; + Data->NameSearch.Multiple.Available = FALSE; + wSetData(&Data->FileName, pszFile); + wSetData(&Data->ShortFileName, pszShortFile); + + ResetDataItem(&Data->IDSearch.Name, L"ID Search - Station Name"); + ResetDataItem(&Data->NameSearch.Single.Name, L"Name Search Single Result - Station Name"); + ResetDataItem(&Data->NameSearch.Single.ID, L"Name Search Single Result - Station ID"); + ResetDataItem(&Data->NameSearch.Multiple.Name, L"Name Search Multiple Result - Station Name"); + ResetDataItem(&Data->NameSearch.Multiple.ID, L"Name Search Multiple Result - Station ID"); + + DataItem.Name = L""; + DataItem.Start = L""; + DataItem.End = L""; + DataItem.Unit = L""; + DataItem.Url = ""; + DataItem.Break = L""; + DataItem.Type = 0; + + Temp = ""; + + // initialize the linked list for update items + Data->UpdateDataCount = 0; + Data->MemUsed = sizeof(WIDATA) + sizeof(WIDATALIST) + (mir_wstrlen(pszShortFile) + mir_wstrlen(pszFile) + 20)*sizeof(wchar_t); + Data->UpdateData = nullptr; + Data->UpdateDataTail = nullptr; + + // initialize the icon assignment list + for (int i = 0; i < 10; i++) + WICondListInit(&Data->CondList[i]); + + while (!feof(pfile)) { + // determine current tag + + if (fgets(Line, _countof(Line), pfile) == nullptr) + break; + TrimString(Line); + + // if the line is a group header/footer + if (Line[0] == '[') { + char *chop = strchr(Line + 1, ']'); + if (chop == nullptr) + continue; + + if (Line[1] != '/') { // if it is not a footer (for old ini) + // save the group name + Temp = (char *)mir_alloc(mir_strlen(Line) + 10); + strncpy(Temp, Line + 1, chop - Line - 1); + Temp[chop - Line - 1] = 0; + wfree(&Group); + wSetData(&Group, Temp); + // see if it is a update item, if it is, add a new item to the linked list + // if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") && + // strcmpi(Group, "NAME SEARCH")) + // wSetData(&DataItem.Name, Group); + if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") && + _stricmp(Group, "NAME SEARCH") && _stricmp(Group, "ICONS")) { + wSetData(&DataItem.Name, Temp); + DataItem.Type = WID_NORMAL; + WIItemListAdd(&DataItem, Data); + Data->UpdateDataCount++; + } + mir_free(Temp); + } + else { + wfree(&Group); + wSetData(&Group, ""); + } + } + // ignore comments and all lines without an '=' + Value = strstr(Line, "="); + if (Value == nullptr) continue; + + // get the string before '=' (ValName) and after '=' (Value) + ValName = (char *)mir_alloc(mir_strlen(Line) + 1); + strncpy(ValName, Line, Value - Line); + ValName[Value - Line] = 0; + Value++; + ConvertBackslashes(Value); + // store the value for each string + if (!_stricmp(Group, "HEADER")) { + if (!_stricmp(ValName, "NAME")) wSetData(&Data->DisplayName, Value); + else if (!_stricmp(ValName, "INTERNAL NAME")) wSetData(&Data->InternalName, Value); + else if (!_stricmp(ValName, "DESCRIPTION")) wSetData(&Data->Description, Value); + else if (!_stricmp(ValName, "AUTHOR")) wSetData(&Data->Author, Value); + else if (!_stricmp(ValName, "VERSION")) wSetData(&Data->Version, Value); + } + else if (!_stricmp(Group, "DEFAULT")) { + if (!_stricmp(ValName, "DEFAULT URL")) wSetData(&Data->DefaultURL, Value); + else if (!_stricmp(ValName, "DEFAULT MAP")) wSetData(&Data->DefaultMap, Value); + else if (!_stricmp(ValName, "UPDATE URL")) wSetData(&Data->UpdateURL, Value); + else if (!_stricmp(ValName, "UPDATE URL2")) wSetData(&Data->UpdateURL2, Value); + else if (!_stricmp(ValName, "UPDATE URL3")) wSetData(&Data->UpdateURL3, Value); + else if (!_stricmp(ValName, "UPDATE URL4")) wSetData(&Data->UpdateURL4, Value); + else if (!_stricmp(ValName, "COOKIE")) wSetData(&Data->Cookie, Value); + else if (!_stricmp(ValName, "USERAGENT")) wSetData(&Data->UserAgent, Value); + } + else if (!_stricmp(Group, "ID SEARCH")) { + if (!_stricmp(ValName, "AVAILABLE")) { + if (!_stricmp(Value, "TRUE")) Data->IDSearch.Available = TRUE; + else Data->IDSearch.Available = FALSE; + } + else if (!_stricmp(ValName, "SEARCH URL")) wSetData(&Data->IDSearch.SearchURL, Value); + else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->IDSearch.NotFoundStr, Value); + else if (!_stricmp(ValName, "NAME START")) wSetData(&Data->IDSearch.Name.Start, Value); + else if (!_stricmp(ValName, "NAME END")) wSetData(&Data->IDSearch.Name.End, Value); + } + else if (!_stricmp(Group, "NAME SEARCH")) { + if (!_stricmp(ValName, "SINGLE RESULT")) { + if (!_stricmp(Value, "TRUE")) Data->NameSearch.Single.Available = TRUE; + else Data->NameSearch.Single.Available = FALSE; + } + else if (!_stricmp(ValName, "MULTIPLE RESULT")) { + if (!_stricmp(Value, "TRUE")) Data->NameSearch.Multiple.Available = TRUE; + else Data->NameSearch.Multiple.Available = FALSE; + } + else if (!_stricmp(ValName, "SEARCH URL")) wSetData(&Data->NameSearch.SearchURL, Value); + else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->NameSearch.NotFoundStr, Value); + else if (!_stricmp(ValName, "SINGLE RESULT STR")) wSetData(&Data->NameSearch.SingleStr, Value); + else if (!_stricmp(ValName, "SINGLE FIRST")) wSetData(&Data->NameSearch.Single.First, Value); + else if (!_stricmp(ValName, "SINGLE NAME START"))wSetData(&Data->NameSearch.Single.Name.Start, Value); + else if (!_stricmp(ValName, "SINGLE NAME END")) wSetData(&Data->NameSearch.Single.Name.End, Value); + else if (!_stricmp(ValName, "SINGLE ID START")) wSetData(&Data->NameSearch.Single.ID.Start, Value); + else if (!_stricmp(ValName, "SINGLE ID END")) wSetData(&Data->NameSearch.Single.ID.End, Value); + else if (!_stricmp(ValName, "MULT FIRST")) wSetData(&Data->NameSearch.Multiple.First, Value); + else if (!_stricmp(ValName, "MULT NAME START")) wSetData(&Data->NameSearch.Multiple.Name.Start, Value); + else if (!_stricmp(ValName, "MULT NAME END")) wSetData(&Data->NameSearch.Multiple.Name.End, Value); + else if (!_stricmp(ValName, "MULT ID START")) wSetData(&Data->NameSearch.Multiple.ID.Start, Value); + else if (!_stricmp(ValName, "MULT ID END")) wSetData(&Data->NameSearch.Multiple.ID.End, Value); + } + else if (!_stricmp(Group, "ICONS")) { + for (int i = 0; i < 10; i++) { + if (!_stricmp(ValName, statusStr[i])) { + WICondListAdd(Value, &Data->CondList[i]); + break; + } + } + } + else if (Data->UpdateDataCount != 0) { + if (!_stricmp(ValName, "START")) wSetData(&Data->UpdateDataTail->Item.Start, Value); + else if (!_stricmp(ValName, "SOURCE")) wSetData(&Data->UpdateDataTail->Item.Start, Value); + else if (!_stricmp(ValName, "END")) wSetData(&Data->UpdateDataTail->Item.End, Value); + else if (!_stricmp(ValName, "UNIT")) wSetData(&Data->UpdateDataTail->Item.Unit, Value); + else if (!_stricmp(ValName, "URL")) wSetData(&Data->UpdateDataTail->Item.Url, Value); + else if (!_stricmp(ValName, "HIDDEN")) { + if (!_stricmp(Value, "TRUE")) { + wchar_t *nm = Data->UpdateDataTail->Item.Name; + size_t len = mir_wstrlen(nm) + 1; + + Data->UpdateDataTail->Item.Name = nm = (wchar_t*)mir_realloc(nm, sizeof(wchar_t)*(len + 3)); + memmove(nm + 1, nm, len*sizeof(wchar_t)); + *nm = '#'; + } + } + else if (!_stricmp(ValName, "SET DATA")) { + Data->UpdateDataTail->Item.Type = WID_SET; + wSetData(&Data->UpdateDataTail->Item.End, Value); + } + else if (!_stricmp(ValName, "BREAK DATA")) { + Data->UpdateDataTail->Item.Type = WID_BREAK; + wSetData(&Data->UpdateDataTail->Item.Break, Value); + } + } + // recalculate memory used + Data->MemUsed += (mir_strlen(Value) + 10); + wfree(&ValName); + } + // calcualate memory used for the ini and close the file + Data->MemUsed += sizeof(WIDATAITEMLIST)*Data->UpdateDataCount; + Data->Enabled = TRUE; // enable the service + fclose(pfile); + wfree(&Group); + } +} + +//============ LOADING INI FILES ============ +// +// load the weather update data form INI files +bool LoadWIData(bool dial) +{ + // make sure that the current service data list is empty + WITail = nullptr; + WIHead = WITail; + + // find all *.ini file in the plugin\weather directory + wchar_t szSearchPath[MAX_PATH], FileName[MAX_PATH]; + GetModuleFileName(GetModuleHandle(nullptr), szSearchPath, _countof(szSearchPath)); + wchar_t *chop = wcsrchr(szSearchPath, '\\'); + if (chop == nullptr) + return false; + *chop = '\0'; + mir_wstrncat(szSearchPath, L"\\Plugins\\Weather\\*.ini", _countof(szSearchPath) - mir_wstrlen(szSearchPath)); + wcsncpy(FileName, szSearchPath, MAX_PATH - 1); + + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(szSearchPath, &fd); + + + // load the content of the ini file into memory + if (hFind != INVALID_HANDLE_VALUE) { + do { + chop = wcsrchr(FileName, '\\'); + chop[1] = '\0'; + mir_wstrncat(FileName, fd.cFileName, _countof(FileName) - mir_wstrlen(FileName)); + if (mir_wstrcmpi(fd.cFileName, L"SAMPLE_INI.INI")) { + WIDATA Data; + LoadStationData(FileName, fd.cFileName, &Data); + if (Data.Enabled) + WIListAdd(Data); + } + // look through the entire "plugins\weather" directory + } while (FindNextFile(hFind, &fd)); + FindClose(hFind); + } + + if (WIHead == nullptr) { + // no ini found, display an error message box. + if (dial) + hWndSetup = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_SETUP), nullptr, DlgProcSetup); + else + MessageBox(nullptr, + TranslateT("No update data file is found. Please check your Plugins\\Weather directory."), + TranslateT("Weather Protocol"), MB_OK | MB_ICONERROR); + return false; + } + return true; +} + +//============ FREE WIDATA ITEM FROM MEMORY ============ +// +// free the WIDATA struct from memory +// Data = the struct to be freed +static void FreeWIData(WIDATA *Data) +{ + // free update items linked list first + WIDATAITEMLIST *WItem = Data->UpdateData; + while (WItem != nullptr) { + Data->UpdateData = WItem->Next; + FreeDataItem(&WItem->Item); + mir_free(WItem); + WItem = Data->UpdateData; + } + + // free the strings in the rest of the struct + wfree(&Data->DisplayName); + wfree(&Data->InternalName); + wfree(&Data->Description); + wfree(&Data->Author); + wfree(&Data->Version); + wfree(&Data->DefaultURL); + wfree(&Data->DefaultMap); + wfree(&Data->UpdateURL); + wfree(&Data->UpdateURL2); + wfree(&Data->UpdateURL3); + wfree(&Data->UpdateURL4); + wfree(&Data->Cookie); + wfree(&Data->UserAgent); + wfree(&Data->IDSearch.SearchURL); + wfree(&Data->IDSearch.NotFoundStr); + FreeDataItem(&Data->IDSearch.Name); + wfree(&Data->NameSearch.SearchURL); + wfree(&Data->NameSearch.NotFoundStr); + wfree(&Data->NameSearch.SingleStr); + wfree(&Data->NameSearch.Single.First); + FreeDataItem(&Data->NameSearch.Single.Name); + FreeDataItem(&Data->NameSearch.Single.ID); + wfree(&Data->NameSearch.Multiple.First); + FreeDataItem(&Data->NameSearch.Multiple.Name); + FreeDataItem(&Data->NameSearch.Multiple.ID); + wfree(&Data->ShortFileName); + wfree(&Data->FileName); + for (int i = 0; i < 10; i++) + DestroyCondList(&Data->CondList[i]); +} + +// remove all service data from memory +void DestroyWIList(void) +{ + // free the list one by one + while (WIHead != nullptr) { + WIDATALIST *wi = WIHead; + WIHead = wi->next; + FreeWIData(&wi->Data); // free the data struct + mir_free(wi); + } + + // make sure the entire list is clear + WITail = nullptr; +} |