From 44323255f6e922e5e2ade2d0c59ca0fe2f532967 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 9 Apr 2023 17:04:00 +0300 Subject: fixes #3479 (StopSpam: duplicate setting removed) --- plugins/StopSpamPlus/res/stopspam.rc | 4 +- plugins/StopSpamPlus/src/events.cpp | 28 +++++++------- plugins/StopSpamPlus/src/options.cpp | 56 +++++++++++++-------------- plugins/StopSpamPlus/src/resource.h | 1 - plugins/StopSpamPlus/src/services.cpp | 56 +-------------------------- plugins/StopSpamPlus/src/settings.cpp | 25 ++---------- plugins/StopSpamPlus/src/settings.h | 23 ----------- plugins/StopSpamPlus/src/stdafx.h | 18 +++++++-- plugins/StopSpamPlus/src/stopspam.cpp | 26 ++++++------- plugins/StopSpamPlus/src/version.h | 2 +- plugins/StopSpamPlus/stopspam.vcxproj | 1 - plugins/StopSpamPlus/stopspam.vcxproj.filters | 3 -- 12 files changed, 75 insertions(+), 168 deletions(-) delete mode 100644 plugins/StopSpamPlus/src/settings.h (limited to 'plugins/StopSpamPlus') diff --git a/plugins/StopSpamPlus/res/stopspam.rc b/plugins/StopSpamPlus/res/stopspam.rc index 2f4b414983..dd81fc4a9c 100644 --- a/plugins/StopSpamPlus/res/stopspam.rc +++ b/plugins/StopSpamPlus/res/stopspam.rc @@ -66,9 +66,7 @@ BEGIN CONTROL "Add contact permanently",ID_ADDPERMANENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,121,282,8 CONTROL "Enable auth. requests blocking",ID_HANDLEAUTHREQ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,133,270,8 CONTROL "Answer is not case sensitive",ID_NOTCASESENS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,145,282,8 - CONTROL "Remove all temporary contacts after restart",ID_REMOVE_TMP_ALL, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,157,282,8 - CONTROL "Log Spammers to system history",ID_HISTORY_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,169,282,8 + CONTROL "Log Spammers to system history",ID_HISTORY_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,157,282,8 END diff --git a/plugins/StopSpamPlus/src/events.cpp b/plugins/StopSpamPlus/src/events.cpp index 7ce72a91b9..08da0fbf42 100644 --- a/plugins/StopSpamPlus/src/events.cpp +++ b/plugins/StopSpamPlus/src/events.cpp @@ -10,7 +10,7 @@ int OnDbEventAdded(WPARAM, LPARAM lParam) return 0; // if event is in protocol that is not despammed - if (g_sets.ProtoDisabled(dbei.szModule)) + if (g_plugin.ProtoDisabled(dbei.szModule)) return 0; // event is an auth request @@ -20,18 +20,18 @@ int OnDbEventAdded(WPARAM, LPARAM lParam) // if request is from unknown or not marked Answered contact //and if I don't sent message to this contact if (!Contact::OnList(hcntct) && !g_plugin.getByte(hcntct, DB_KEY_ANSWERED) && !IsExistMyMessage(hcntct)) { - if (!g_sets.HandleAuthReq) { - char *buf = mir_utf8encodeW(variables_parse(g_sets.getReply(), hcntct).c_str()); + if (!g_plugin.HandleAuthReq) { + char *buf = mir_utf8encodeW(variables_parse(g_plugin.getReply(), hcntct).c_str()); ProtoChainSend(hcntct, PSS_MESSAGE, 0, (LPARAM)buf); mir_free(buf); } // ...send message - CallProtoService(dbei.szModule, PS_AUTHDENY, hDbEvent, (LPARAM)_T2A(variables_parse(g_sets.getReply(), hcntct).c_str())); + CallProtoService(dbei.szModule, PS_AUTHDENY, hDbEvent, (LPARAM)_T2A(variables_parse(g_plugin.getReply(), hcntct).c_str())); Contact::RemoveFromList(hcntct); Contact::Hide(hcntct); - if (!g_sets.HistLog) + if (!g_plugin.HistLog) db_event_delete(hDbEvent); return 1; } @@ -47,7 +47,7 @@ int OnDbEventFilterAdd(WPARAM w, LPARAM l) return 0; // if event is in protocol that is not despammed - if (g_sets.ProtoDisabled(dbei->szModule)) + if (g_plugin.ProtoDisabled(dbei->szModule)) // ...let the event go its way return 0; @@ -89,17 +89,17 @@ int OnDbEventFilterAdd(WPARAM w, LPARAM l) } // if message equal right answer... - tstring answers = variables_parse(g_sets.Answer, hContact); - answers.append(g_sets.AnswSplitString); + tstring answers = variables_parse(g_plugin.Answer, hContact); + answers.append(g_plugin.AnswSplitString); tstring::size_type pos = 0; tstring::size_type prev_pos = 0; - while ((pos = answers.find(g_sets.AnswSplitString, pos)) != tstring::npos) { + while ((pos = answers.find(g_plugin.AnswSplitString, pos)) != tstring::npos) { // get one of answers and trim witespace chars tstring answer = trim(answers.substr(prev_pos, pos - prev_pos)); // if answer not empty if (answer.length() > 0) { // if message equal right answer... - if (g_sets.AnswNotCaseSens ? !mir_wstrcmpi(message.c_str(), answer.c_str()) : !mir_wstrcmp(message.c_str(), answer.c_str())) { + if (g_plugin.AnswNotCaseSens ? !mir_wstrcmpi(message.c_str(), answer.c_str()) : !mir_wstrcmp(message.c_str(), answer.c_str())) { // unhide contact Contact::Hide(hContact, false); @@ -107,12 +107,12 @@ int OnDbEventFilterAdd(WPARAM w, LPARAM l) g_plugin.setByte(hContact, DB_KEY_ANSWERED, 1); //add contact permanently - if (g_sets.AddPermanent) + if (g_plugin.AddPermanent) Contact::PutOnList(hContact); // send congratulation - char * buf = mir_utf8encodeW(variables_parse(g_sets.getCongrats(), hContact).c_str()); + char * buf = mir_utf8encodeW(variables_parse(g_plugin.getCongrats(), hContact).c_str()); ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)buf); mir_free(buf); @@ -126,9 +126,9 @@ int OnDbEventFilterAdd(WPARAM w, LPARAM l) // if message message does not contain infintite talk protection prefix // and question count for this contact is less then maximum const wchar_t *pwszPrefix = TranslateT("StopSpam automatic message:\r\n"); - if ((!g_sets.InfTalkProtection || tstring::npos == message.find(pwszPrefix)) && (!g_sets.MaxQuestCount || g_plugin.getDword(hContact, DB_KEY_QUESTCOUNT) < g_sets.MaxQuestCount)) { + if ((!g_plugin.InfTalkProtection || tstring::npos == message.find(pwszPrefix)) && (!g_plugin.MaxQuestCount || g_plugin.getDword(hContact, DB_KEY_QUESTCOUNT) < g_plugin.MaxQuestCount)) { // send question - tstring q = pwszPrefix + variables_parse(g_sets.getQuestion(), hContact); + tstring q = pwszPrefix + variables_parse(g_plugin.getQuestion(), hContact); char * buf = mir_utf8encodeW(q.c_str()); diff --git a/plugins/StopSpamPlus/src/options.cpp b/plugins/StopSpamPlus/src/options.cpp index f4187a47c2..2d55ef9309 100644 --- a/plugins/StopSpamPlus/src/options.cpp +++ b/plugins/StopSpamPlus/src/options.cpp @@ -5,7 +5,7 @@ const wchar_t pluginDescription[] = LPGENW("No more spam! Robots can't go! Only class COptMainDlg : public CDlgBase { CCtrlEdit edtCount, edtDescr; - CCtrlCheck chk1, chk2, chk3, chk4, chk5, chk6; + CCtrlCheck chk1, chk2, chk3, chk4, chk6; public: COptMainDlg() : @@ -16,17 +16,15 @@ public: chk2(this, ID_ADDPERMANENT), chk3(this, ID_HANDLEAUTHREQ), chk4(this, ID_NOTCASESENS), - chk5(this, ID_REMOVE_TMP_ALL), chk6(this, ID_HISTORY_LOG) { - CreateLink(edtCount, g_sets.MaxQuestCount); - - CreateLink(chk1, g_sets.InfTalkProtection); - CreateLink(chk2, g_sets.AddPermanent); - CreateLink(chk3, g_sets.HandleAuthReq); - CreateLink(chk4, g_sets.AnswNotCaseSens); - CreateLink(chk5, g_sets.RemTmpAll); - CreateLink(chk6, g_sets.HistLog); + CreateLink(edtCount, g_plugin.MaxQuestCount); + + CreateLink(chk1, g_plugin.InfTalkProtection); + CreateLink(chk2, g_plugin.AddPermanent); + CreateLink(chk3, g_plugin.HandleAuthReq); + CreateLink(chk4, g_plugin.AnswNotCaseSens); + CreateLink(chk6, g_plugin.HistLog); } bool OnInitDialog() override @@ -57,11 +55,11 @@ public: btnHelp.OnClick = Callback(this, &COptMessageDlg::onHelp); btnRestore.OnClick = Callback(this, &COptMessageDlg::onRestore); - CreateLink(edtReply, g_sets.AuthRepl); - CreateLink(edtAnswer, g_sets.Answer); - CreateLink(edtQuestion, g_sets.Question); - CreateLink(edtCongrat, g_sets.Congratulation); - CreateLink(edtDivider, g_sets.AnswSplitString); + CreateLink(edtReply, g_plugin.AuthRepl); + CreateLink(edtAnswer, g_plugin.Answer); + CreateLink(edtQuestion, g_plugin.Question); + CreateLink(edtCongrat, g_plugin.Congratulation); + CreateLink(edtDivider, g_plugin.AnswSplitString); } bool OnInitDialog() override @@ -69,9 +67,9 @@ public: variables_skin_helpbutton(m_hwnd, IDC_VARS); btnHelp.Enable(ServiceExists(MS_VARS_FORMATSTRING)); - edtQuestion.SetText(g_sets.getQuestion()); - edtCongrat.SetText(g_sets.getCongrats()); - edtReply.SetText(g_sets.getReply()); + edtQuestion.SetText(g_plugin.getQuestion()); + edtCongrat.SetText(g_plugin.getCongrats()); + edtReply.SetText(g_plugin.getReply()); return true; } @@ -82,15 +80,15 @@ public: void onRestore(CCtrlButton*) { - g_plugin.delSetting(g_sets.AuthRepl.GetDBSettingName()); - g_plugin.delSetting(g_sets.Question.GetDBSettingName()); - g_plugin.delSetting(g_sets.Congratulation.GetDBSettingName()); - - edtQuestion.SetText(g_sets.getQuestion()); - edtAnswer.SetText(g_sets.Answer.Default()); - edtCongrat.SetText(g_sets.getCongrats()); - edtReply.SetText(g_sets.getReply()); - edtDivider.SetText(g_sets.AnswSplitString.Default()); + g_plugin.delSetting(g_plugin.AuthRepl.GetDBSettingName()); + g_plugin.delSetting(g_plugin.Question.GetDBSettingName()); + g_plugin.delSetting(g_plugin.Congratulation.GetDBSettingName()); + + edtQuestion.SetText(g_plugin.getQuestion()); + edtAnswer.SetText(g_plugin.Answer.Default()); + edtCongrat.SetText(g_plugin.getCongrats()); + edtReply.SetText(g_plugin.getReply()); + edtDivider.SetText(g_plugin.AnswSplitString.Default()); NotifyChange(); } @@ -132,7 +130,7 @@ public: item.lParam = (LPARAM)pa->szModuleName; item.pszText = pa->tszAccountName; int idx = m_accounts.InsertItem(&item); - m_accounts.SetCheckState(idx, !g_sets.ProtoDisabled(pa->szModuleName)); + m_accounts.SetCheckState(idx, !g_plugin.ProtoDisabled(pa->szModuleName)); } return true; } @@ -153,7 +151,7 @@ public: out << (char*)item.lParam << " "; } - g_sets.DisabledProtoList = (char*)out.str().c_str(); + g_plugin.DisabledProtoList = (char*)out.str().c_str(); return true; } diff --git a/plugins/StopSpamPlus/src/resource.h b/plugins/StopSpamPlus/src/resource.h index 9eecb574c0..a4e7c05b61 100644 --- a/plugins/StopSpamPlus/src/resource.h +++ b/plugins/StopSpamPlus/src/resource.h @@ -19,7 +19,6 @@ #define ID_NOTCASESENS 1013 #define ID_DIVIDER 1014 #define IDC_VARS 1015 -#define ID_REMOVE_TMP_ALL 1016 #define ID_HISTORY_LOG 1017 // Next default values for new objects diff --git a/plugins/StopSpamPlus/src/services.cpp b/plugins/StopSpamPlus/src/services.cpp index 90a14444a1..ed57888afb 100644 --- a/plugins/StopSpamPlus/src/services.cpp +++ b/plugins/StopSpamPlus/src/services.cpp @@ -6,7 +6,7 @@ INT_PTR IsContactPassed(WPARAM hContact, LPARAM /*lParam*/) if (szProto == nullptr) return CS_PASSED; - if (!g_sets.ProtoDisabled(szProto)) + if (!g_plugin.ProtoDisabled(szProto)) return CS_PASSED; if (g_plugin.getByte(hContact, DB_KEY_ANSWERED)) @@ -20,57 +20,3 @@ INT_PTR IsContactPassed(WPARAM hContact, LPARAM /*lParam*/) return CS_NOTPASSED; } - -INT_PTR RemoveTempContacts(WPARAM, LPARAM lParam) -{ - for (MCONTACT hContact = db_find_first(); hContact;) { - MCONTACT hNext = db_find_next(hContact); - ptrW szGroup(Clist_GetGroup(hContact)); - - if (!Contact::OnList(hContact) || (szGroup != NULL && (wcsstr(szGroup, L"Not In List") || wcsstr(szGroup, TranslateT("Not In List"))))) { - char *szProto = Proto_GetBaseAccountName(hContact); - if (szProto != nullptr) { - // Check if protocol uses server side lists - uint32_t caps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0); - if (caps & PF1_SERVERCLIST) { - int status = Proto_GetStatus(szProto); - if (status == ID_STATUS_OFFLINE || IsStatusConnecting(status)) - // Set a flag so we remember to delete the contact when the protocol goes online the next time - db_set_b(hContact, "CList", "Delete", 1); - else - db_delete_contact(hContact); - } - } - } - - hContact = hNext; - } - - int hGroup = 1; - wchar_t *group_name; - do { - group_name = Clist_GroupGetName(hGroup, nullptr); - if (group_name != nullptr && wcsstr(group_name, TranslateT("Not In List"))) { - uint8_t ConfirmDelete = Clist::ConfirmDelete; - if (ConfirmDelete) - db_set_b(0, "CList", "ConfirmDelete", 0); - - Clist_GroupDelete(hGroup); - if (ConfirmDelete) - db_set_b(0, "CList", "ConfirmDelete", ConfirmDelete); - break; - } - hGroup++; - } while (group_name); - if (!lParam) - MessageBox(nullptr, TranslateT("Complete"), TranslateT(MODULENAME), MB_ICONINFORMATION); - - return 0; -} - -int OnSystemModulesLoaded(WPARAM, LPARAM) -{ - if (g_sets.RemTmpAll) - RemoveTempContacts(0, 1); - return 0; -} diff --git a/plugins/StopSpamPlus/src/settings.cpp b/plugins/StopSpamPlus/src/settings.cpp index 01d11c7570..5c7dc5d495 100644 --- a/plugins/StopSpamPlus/src/settings.cpp +++ b/plugins/StopSpamPlus/src/settings.cpp @@ -1,39 +1,20 @@ #include "stdafx.h" -Settings g_sets; - ///////////////////////////////////////////////////////////////////////////////////////// -Settings::Settings() : - Question(MODULENAME, "Question"), - AuthRepl(MODULENAME, "AuthReply"), - Answer(MODULENAME, "Answer", L"nospam"), - Congratulation(MODULENAME, "Congratulation"), - DisabledProtoList(MODULENAME, "DisabledProtoList", "MetaContacts RSSNews"), - InfTalkProtection(MODULENAME, "InfTalkProtection", 1), - AddPermanent(MODULENAME, "AddPermanent", 0), - HandleAuthReq(MODULENAME, "HandleAuthReq", 0), - MaxQuestCount(MODULENAME, "MaxQuestCount", 2), - AnswNotCaseSens(MODULENAME, "AnswNotCaseSens", 1), - AnswSplitString(MODULENAME, "AnswSplitString", L"|"), - RemTmpAll(MODULENAME, "RemTmpAll", 1), - HistLog(MODULENAME, "HistLog", 0) -{ -} - -const wchar_t* Settings::getQuestion() +const wchar_t* CMPlugin::getQuestion() { const wchar_t *res = Question; return (res != nullptr) ? res : TranslateW(L"Spammers made me to install small anti-spam system you are now speaking with. Please reply \"nospam\" without quotes and spaces if you want to contact me."); } -const wchar_t* Settings::getReply() +const wchar_t* CMPlugin::getReply() { const wchar_t *res = AuthRepl; return (res != nullptr) ? res : TranslateW(L"StopSpam: send a message and reply to an anti-spam bot question."); } -const wchar_t* Settings::getCongrats() +const wchar_t* CMPlugin::getCongrats() { const wchar_t *res = Congratulation; return (res != nullptr) ? res : TranslateW(L"Congratulations! You just passed human/robot test. Now you can write me a message."); diff --git a/plugins/StopSpamPlus/src/settings.h b/plugins/StopSpamPlus/src/settings.h deleted file mode 100644 index 42a7f2125d..0000000000 --- a/plugins/StopSpamPlus/src/settings.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -struct Settings -{ - Settings(); - - CMOption InfTalkProtection, AddPermanent, HandleAuthReq, AnswNotCaseSens, RemTmpAll, HistLog; - CMOption Question, AuthRepl, Answer, Congratulation, AnswSplitString; - CMOption DisabledProtoList; - CMOption MaxQuestCount; - - const wchar_t* getQuestion(); - const wchar_t* getReply(); - const wchar_t* getCongrats(); - - bool ProtoDisabled(const char *proto) - { - std::string temp(proto); temp += ' '; - return strstr(DisabledProtoList, temp.c_str()) != nullptr; - } -}; - -extern Settings g_sets; diff --git a/plugins/StopSpamPlus/src/stdafx.h b/plugins/StopSpamPlus/src/stdafx.h index 2574ed6da7..84916a972f 100644 --- a/plugins/StopSpamPlus/src/stdafx.h +++ b/plugins/StopSpamPlus/src/stdafx.h @@ -28,7 +28,6 @@ typedef std::wstring tstring; #include "version.h" #include "resource.h" -#include "settings.h" #define MODULENAME LPGEN("StopSpam") @@ -39,6 +38,21 @@ struct CMPlugin : public PLUGIN { CMPlugin(); + CMOption InfTalkProtection, AddPermanent, HandleAuthReq, AnswNotCaseSens, HistLog; + CMOption Question, AuthRepl, Answer, Congratulation, AnswSplitString; + CMOption DisabledProtoList; + CMOption MaxQuestCount; + + const wchar_t* getQuestion(); + const wchar_t* getReply(); + const wchar_t* getCongrats(); + + bool ProtoDisabled(const char *proto) + { + std::string temp(proto); temp += ' '; + return strstr(DisabledProtoList, temp.c_str()) != nullptr; + } + int Load() override; }; @@ -49,8 +63,6 @@ tstring variables_parse(const wchar_t *tstrFormat, MCONTACT hContact); tstring trim(tstring const &tstr, tstring const &trimChars = L" \f\n\r\t\v"); INT_PTR IsContactPassed(WPARAM wParam, LPARAM /*lParam*/); -INT_PTR RemoveTempContacts(WPARAM wParam,LPARAM lParam); -int OnSystemModulesLoaded(WPARAM wParam, LPARAM lParam); int OnDbEventAdded(WPARAM wParam, LPARAM lParam); int OnDbEventFilterAdd(WPARAM w, LPARAM l); int OnOptInit(WPARAM w, LPARAM l); diff --git a/plugins/StopSpamPlus/src/stopspam.cpp b/plugins/StopSpamPlus/src/stopspam.cpp index 8c609cf5e6..c042e4fd4c 100644 --- a/plugins/StopSpamPlus/src/stopspam.cpp +++ b/plugins/StopSpamPlus/src/stopspam.cpp @@ -19,7 +19,19 @@ PLUGININFOEX pluginInfoEx = { }; CMPlugin::CMPlugin() : - PLUGIN(MODULENAME, pluginInfoEx) + PLUGIN(MODULENAME, pluginInfoEx), + Question(MODULENAME, "Question"), + AuthRepl(MODULENAME, "AuthReply"), + Answer(MODULENAME, "Answer", L"nospam"), + Congratulation(MODULENAME, "Congratulation"), + DisabledProtoList(MODULENAME, "DisabledProtoList", "MetaContacts RSSNews"), + InfTalkProtection(MODULENAME, "InfTalkProtection", 1), + AddPermanent(MODULENAME, "AddPermanent", 0), + HandleAuthReq(MODULENAME, "HandleAuthReq", 0), + MaxQuestCount(MODULENAME, "MaxQuestCount", 2), + AnswNotCaseSens(MODULENAME, "AnswNotCaseSens", 1), + AnswSplitString(MODULENAME, "AnswSplitString", L"|"), + HistLog(MODULENAME, "HistLog", 0) {} ///////////////////////////////////////////////////////////////////////////////////////// @@ -28,21 +40,9 @@ int CMPlugin::Load() { CreateServiceFunction(MS_STOPSPAM_CONTACTPASSED, IsContactPassed); - HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded); HookEvent(ME_DB_EVENT_ADDED, OnDbEventAdded); HookEvent(ME_DB_EVENT_FILTER_ADD, OnDbEventFilterAdd); HookEvent(ME_OPT_INITIALISE, OnOptInit); HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnDbContactSettingchanged); - - // Add deleting temporary contacts - CMenuItem mi(&g_plugin); - SET_UID(mi, 0xf2164e17, 0xa4c1, 0x4b07, 0xae, 0x81, 0x9e, 0xae, 0x7f, 0xa2, 0x55, 0x13); - mi.position = -0x7FFFFFFF; - mi.flags = CMIF_UNICODE; - mi.hIcolibItem = Skin_LoadIcon(SKINICON_OTHER_MIRANDA); - mi.name.w = LPGENW("Remove Temporary Contacts"); - mi.pszService = "StopSpam/RemoveTempContacts"; - Menu_AddMainMenuItem(&mi); - CreateServiceFunction(mi.pszService, RemoveTempContacts); return 0; } diff --git a/plugins/StopSpamPlus/src/version.h b/plugins/StopSpamPlus/src/version.h index 937b1dc493..7d3ce228da 100644 --- a/plugins/StopSpamPlus/src/version.h +++ b/plugins/StopSpamPlus/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 1 #define __RELEASE_NUM 0 -#define __BUILD_NUM 3 +#define __BUILD_NUM 4 #include diff --git a/plugins/StopSpamPlus/stopspam.vcxproj b/plugins/StopSpamPlus/stopspam.vcxproj index 3b8c984e31..ca3ec31db4 100644 --- a/plugins/StopSpamPlus/stopspam.vcxproj +++ b/plugins/StopSpamPlus/stopspam.vcxproj @@ -36,7 +36,6 @@ - diff --git a/plugins/StopSpamPlus/stopspam.vcxproj.filters b/plugins/StopSpamPlus/stopspam.vcxproj.filters index 55c2aee23c..3227d52b41 100644 --- a/plugins/StopSpamPlus/stopspam.vcxproj.filters +++ b/plugins/StopSpamPlus/stopspam.vcxproj.filters @@ -28,9 +28,6 @@ Header Files - - Header Files - Header Files -- cgit v1.2.3