From f04d64869f3b1de54fb343f28f955584780001b8 Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Sat, 26 Nov 2011 15:41:10 +0000 Subject: Project folders rename part 3 git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@215 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- StopSpamPlus/src/eventhooker.cpp | 68 +++++++++++ StopSpamPlus/src/eventhooker.h | 60 +++++++++ StopSpamPlus/src/events.cpp | 254 +++++++++++++++++++++++++++++++++++++++ StopSpamPlus/src/opt_proto.cpp | 137 +++++++++++++++++++++ StopSpamPlus/src/options.cpp | 133 ++++++++++++++++++++ StopSpamPlus/src/services.cpp | 82 +++++++++++++ StopSpamPlus/src/settings.cpp | 59 +++++++++ StopSpamPlus/src/settings.h | 100 +++++++++++++++ StopSpamPlus/src/stopspam.cpp | 107 +++++++++++++++++ StopSpamPlus/src/utils.cpp | 77 ++++++++++++ 10 files changed, 1077 insertions(+) create mode 100644 StopSpamPlus/src/eventhooker.cpp create mode 100644 StopSpamPlus/src/eventhooker.h create mode 100644 StopSpamPlus/src/events.cpp create mode 100644 StopSpamPlus/src/opt_proto.cpp create mode 100644 StopSpamPlus/src/options.cpp create mode 100644 StopSpamPlus/src/services.cpp create mode 100644 StopSpamPlus/src/settings.cpp create mode 100644 StopSpamPlus/src/settings.h create mode 100644 StopSpamPlus/src/stopspam.cpp create mode 100644 StopSpamPlus/src/utils.cpp (limited to 'StopSpamPlus/src') diff --git a/StopSpamPlus/src/eventhooker.cpp b/StopSpamPlus/src/eventhooker.cpp new file mode 100644 index 0000000..f29e5b7 --- /dev/null +++ b/StopSpamPlus/src/eventhooker.cpp @@ -0,0 +1,68 @@ +/* eventhooker.cpp +* Copyright (C) Miklashevsky Roman +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include "eventhooker.h" + +namespace miranda +{ + namespace + { + std::list eventHookerList; + } + + EventHooker::EventHooker(std::string name, MIRANDAHOOK fun) : name_(name), fun_(fun), handle_(0) + { + eventHookerList.push_back(this); + } + + EventHooker::~EventHooker() + { + eventHookerList.remove(this); + } + + void EventHooker::Hook() + { + handle_ = HookEvent(name_.c_str(), fun_); + } + + void EventHooker::Unhook() + { + if(handle_) + { + UnhookEvent(handle_); + handle_ = 0; + } + } + + void EventHooker::HookAll() + { + for(std::list::iterator it = eventHookerList.begin(); it != eventHookerList.end(); ++it) + { + (*it)->Hook(); + } + } + + void EventHooker::UnhookAll() + { + for(std::list::iterator it = eventHookerList.begin(); it != eventHookerList.end(); ++it) + { + (*it)->Unhook(); + } + } +} diff --git a/StopSpamPlus/src/eventhooker.h b/StopSpamPlus/src/eventhooker.h new file mode 100644 index 0000000..b1ca2ab --- /dev/null +++ b/StopSpamPlus/src/eventhooker.h @@ -0,0 +1,60 @@ +/* eventhooker.h - Helper for hooking events in Miranda. +* Copyright (C) Miklashevsky Roman +* +* To hook event just write +* MIRANDA_HOOK_EVENT('name of the event', wParam, lParam) { 'your code' } +* Include following in your Load function +* miranda::EventHooker::HookAll(); +* And following in your Unload function +* miranda::EventHooker::UnhookAll(); +* That's all +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef EVENTHOOKER_H_C8EAA58A_7C4D_45f7_A88E_0E41FE93754D +#define EVENTHOOKER_H_C8EAA58A_7C4D_45f7_A88E_0E41FE93754D + +#pragma warning( once : 4430 ) + +#include +#include +#include + +namespace miranda +{ + +#define MIRANDA_HOOK_EVENT(NAME, WPARAMNAME, LPARAMNAME) \ + int NAME##_Handler(WPARAM,LPARAM);\ + miranda::EventHooker NAME##_Hooker(NAME, NAME##_Handler);\ + int NAME##_Handler(WPARAM WPARAMNAME, LPARAM LPARAMNAME) + + struct EventHooker + { + EventHooker(std::string name, MIRANDAHOOK fun); + ~EventHooker(); + void Hook(); + void Unhook(); + static void HookAll(); + static void UnhookAll(); + private: + std::string name_; + MIRANDAHOOK fun_; + HANDLE handle_; + }; + +} + +#endif diff --git a/StopSpamPlus/src/events.cpp b/StopSpamPlus/src/events.cpp new file mode 100644 index 0000000..74d4195 --- /dev/null +++ b/StopSpamPlus/src/events.cpp @@ -0,0 +1,254 @@ +#include "../headers.h" + + +MIRANDA_HOOK_EVENT(ME_DB_EVENT_ADDED, wParam, lParam) +{ + HANDLE hDbEvent = (HANDLE)lParam; + + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0); + if(-1 == dbei.cbBlob) + return 0; + + dbei.pBlob = new BYTE[dbei.cbBlob]; + CallService(MS_DB_EVENT_GET, lParam, (LPARAM)&dbei); + + // if event is in protocol that is not despammed + if(plSets->ProtoDisabled(dbei.szModule)) { + delete [] dbei.pBlob; + return 0; + } + + // event is an auth request + if(!(dbei.flags & DBEF_SENT) && !(dbei.flags & DBEF_READ) && dbei.eventType == EVENTTYPE_AUTHREQUEST) + { + HANDLE hcntct=*(HANDLE*)(dbei.pBlob + sizeof(DWORD)); + + // if request is from unknown or not marked Answered contact + //and if I don't sent message to this contact + + if(DBGetContactSettingByte(hcntct, "CList", "NotOnList", 0) && + !DBGetContactSettingByte(hcntct, pluginName, answeredSetting, 0) && + !IsExistMyMessage(hcntct)) + { + if(!plSets->HandleAuthReq.Get()) + { + #ifdef _UNICODE + char * buf=mir_utf8encodeW(variables_parse(plSets->AuthRepl.Get(), hcntct).c_str()); + CallContactService(hcntct, PSS_MESSAGE, PREF_UTF, (LPARAM)buf); + mir_free(buf); + #else + CallContactService(hcntct, PSS_MESSAGE, 0, (LPARAM)(variables_parse(plSets->AuthRepl.Get(), hcntct).c_str())); + #endif + } + char *AuthRepl; + #ifdef _UNICODE + AuthRepl=mir_u2a(variables_parse(plSets->AuthRepl.Get(), hcntct).c_str()); + #else + AuthRepl=variables_parse(plSets->AuthRepl.Get(), hcntct).c_str(); + #endif + // ...send message + std::string allowService = dbei.szModule; + allowService += PS_AUTHDENY; + CallService(allowService.c_str(), (WPARAM)hDbEvent, (LPARAM)AuthRepl); + #ifdef _UNICODE + mir_free(AuthRepl); + #endif + DBWriteContactSettingByte(hcntct, "CList", "NotOnList", 1); + DBWriteContactSettingByte(hcntct, "CList", "Hidden", 1); + if (!plSets->HistLog.Get()) + CallService(MS_DB_EVENT_DELETE, 0, (LPARAM)hDbEvent); + delete [] dbei.pBlob; + return 1; + } + } + delete [] dbei.pBlob; + return 0; +} + +MIRANDA_HOOK_EVENT(ME_DB_EVENT_FILTER_ADD, w, l) +{ + HANDLE hContact = (HANDLE)w; + + if(!l) //fix potential DEP crash + return 0; + DBEVENTINFO * dbei = (DBEVENTINFO*)l; + + // if event is in protocol that is not despammed + if(plSets->ProtoDisabled(dbei->szModule)) + // ...let the event go its way + return 0; + + // if event is not a message, or if the message has been read or sent... + if(dbei->flags & DBEF_SENT || dbei->flags & DBEF_READ || dbei->eventType != EVENTTYPE_MESSAGE ) + // ...let the event go its way + return 0; + + // if message is from known or marked Answered contact + if(DBGetContactSettingByte(hContact, pluginName, answeredSetting, 0)) + // ...let the event go its way + return 0; + + // checking if message from self-added contact + //Contact in Not in list icq group + if(!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) && DBGetContactSettingWord(hContact, dbei->szModule, "SrvGroupId", -1) != 1) + return 0; + + //if I sent message to this contact + if(IsExistMyMessage(hContact)) + return 0; + + // if message is corrupted or empty it cannot be an answer. + if(!dbei->cbBlob || !dbei->pBlob) + // reject processing of the event + return 1; + + tstring message; + + if(dbei->flags & DBEF_UTF){ + WCHAR* msg_u=mir_utf8decodeW((char*)dbei->pBlob); +#ifdef _UNICODE + message = msg_u; +#else + char* msg_a = mir_u2a(msg_u); + message = msg_a; + mir_free(msg_a); +#endif + mir_free(msg_u); + } + else{ +#ifdef _UNICODE + WCHAR* msg_u = mir_a2u((char*)(dbei->pBlob)); + message = msg_u; + mir_free(msg_u); +#else + message = (char*)(dbei->pBlob); +#endif + } + + // if message equal right answer... + tstring answers = variables_parse(plSets->Answer.Get(), hContact); + answers.append(plSets->AnswSplitString.Get()); + tstring::size_type pos = 0; + tstring::size_type prev_pos = 0; + while((pos = answers.find(plSets->AnswSplitString.Get(), 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 (plSets->AnswNotCaseSens.Get() ? + !lstrcmpi(message.c_str(), answer.c_str()) : + !lstrcmp(message.c_str(), answer.c_str()) + ) + { + // unhide contact + DBDeleteContactSetting(hContact, "CList", "Hidden"); + + // mark contact as Answered + DBWriteContactSettingByte(hContact, pluginName, answeredSetting, 1); + + //add contact permanently + if(plSets->AddPermanent.Get()) + DBDeleteContactSetting(hContact, "CList", "NotOnList"); + + // send congratulation + #ifdef _UNICODE + char * buf=mir_utf8encodeW(variables_parse(plSets->Congratulation.Get(), hContact).c_str()); + CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)buf); + mir_free(buf); + #else + CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)(variables_parse(plSets->Congratulation.Get(), hContact).c_str())); + #endif + + // process the event + return 1; + } + } + prev_pos = ++pos; + } + + // if message message does not contain infintite talk protection prefix + // and question count for this contact is less then maximum + if( (!plSets->InfTalkProtection.Get() || tstring::npos==message.find(infTalkProtPrefix)) + && (!plSets->MaxQuestCount.Get() || DBGetContactSettingDword(hContact, pluginName, questCountSetting, 0) < plSets->MaxQuestCount.Get()) ) + { + // send question + tstring q = infTalkProtPrefix + variables_parse((tstring)(plSets->Question), hContact); + +#ifdef _UNICODE + char * buf=mir_utf8encodeW(q.c_str()); + CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)buf); + mir_free(buf); +#else + CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)q.c_str()); +#endif + + // increment question count + DWORD questCount = DBGetContactSettingDword(hContact, pluginName, questCountSetting, 0); + DBWriteContactSettingDword(hContact, pluginName, questCountSetting, questCount + 1); + + // hide contact from contact list + } + DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1); + + // save message from contact + dbei->flags |= DBEF_READ; + CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)dbei); + + // reject processing of the event + return 1; +} + +MIRANDA_HOOK_EVENT(ME_OPT_INITIALISE, w, l) +{ + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.ptszGroup = _T("Message Sessions"); + odp.ptszTitle = _T(pluginName); + odp.position = -1; + odp.hInstance = hInst; + odp.flags = ODPF_TCHAR; + + odp.ptszTab = _T("Main"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_MAIN); + odp.pfnDlgProc = MainDlgProc; + CallService(MS_OPT_ADDPAGE, w, (LPARAM)&odp); + + + odp.ptszTab = _T("Messages"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_MESSAGES); + odp.pfnDlgProc = MessagesDlgProc; + CallService(MS_OPT_ADDPAGE, w, (LPARAM)&odp); + + odp.ptszTab = _T("Protocols"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROTO); + odp.pfnDlgProc = ProtoDlgProc; + CallService(MS_OPT_ADDPAGE, w, (LPARAM)&odp); + + return 0; +} + +MIRANDA_HOOK_EVENT(ME_DB_CONTACT_SETTINGCHANGED, w, l) +{ + HANDLE hContact = (HANDLE)w; + DBCONTACTWRITESETTING * cws = (DBCONTACTWRITESETTING*)l; + + // if CList/NotOnList is being deleted then remove answeredSetting + if(strcmp(cws->szModule, "CList")) + return 0; + if(strcmp(cws->szSetting, "NotOnList")) + return 0; + if(!cws->value.type) + { + DBDeleteContactSetting(hContact, pluginName, answeredSetting); + DBDeleteContactSetting(hContact, pluginName, questCountSetting); + } + + return 0; +} + diff --git a/StopSpamPlus/src/opt_proto.cpp b/StopSpamPlus/src/opt_proto.cpp new file mode 100644 index 0000000..201fba6 --- /dev/null +++ b/StopSpamPlus/src/opt_proto.cpp @@ -0,0 +1,137 @@ +#include "../headers.h" + +struct ProtocolData +{ + char *RealName; + int show,enabled; +}; + +int IsProtoIM(const PROTOACCOUNT* pa) +{ + return (CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM); +} + +int FillTree(HWND hwnd) +{ + ProtocolData *PD; + int i,n; + PROTOACCOUNT** pa; + + TVINSERTSTRUCT tvis; + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + + TreeView_DeleteAllItems(hwnd); + + if(CallService(MS_PROTO_ENUMACCOUNTS, (LPARAM)&n, (WPARAM)&pa)) + return FALSE; + + for ( i = 0; i < n; i++ ) { + if(IsAccountEnabled( pa[i] )){ + PD = ( ProtocolData* )mir_alloc( sizeof( ProtocolData )); + PD->RealName = pa[i]->szModuleName; + PD->enabled = IsProtoIM( pa[i]); + PD->show = PD->enabled ? (plSets->ProtoDisabled(PD->RealName)?1:0) : 100; + + tvis.item.lParam = ( LPARAM )PD; + tvis.item.pszText = pa[i]->tszAccountName; + tvis.item.iImage = tvis.item.iSelectedImage = PD->show; + TreeView_InsertItem( hwnd, &tvis ); + } + } + + return 0; +} + +INT_PTR CALLBACK ProtoDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndProto = GetDlgItem(hwnd, IDC_PROTO); + + switch (msg) + { + + case WM_INITDIALOG: + TranslateDialogDefault(hwnd); + + SetWindowLong(hwndProto, GWL_STYLE, GetWindowLong(hwndProto, GWL_STYLE) | TVS_NOHSCROLL); + { + HIMAGELIST himlCheckBoxes = ImageList_Create( GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), ILC_COLOR32|ILC_MASK, 2, 2 ); + HICON Icon; + Icon=(HICON)LoadSkinnedIcon(SKINICON_OTHER_NOTICK); + ImageList_AddIcon(himlCheckBoxes, Icon); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)Icon, 0); + Icon=(HICON)LoadSkinnedIcon(SKINICON_OTHER_TICK); + ImageList_AddIcon(himlCheckBoxes, Icon); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)Icon, 0); + + TreeView_SetImageList(hwndProto, himlCheckBoxes, TVSIL_NORMAL); + } + + FillTree(hwndProto); + return TRUE; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + if (((LPNMHDR)lParam)->code == PSN_APPLY ) { + + std::ostringstream out; + + TVITEM tvi; + tvi.hItem = TreeView_GetRoot(hwndProto); + tvi.cchTextMax = 32; + tvi.mask = TVIF_PARAM | TVIF_HANDLE; + + while ( tvi.hItem != NULL ) { + TreeView_GetItem(hwndProto, &tvi); + + if (tvi.lParam!=0) { + ProtocolData* ppd = ( ProtocolData* )tvi.lParam; + if(ppd->enabled && ppd->show) + out << ppd->RealName << " "; + } + + tvi.hItem = TreeView_GetNextSibling(hwndProto, tvi.hItem ); + } + + plSets->DisabledProtoList=out.str(); + } + break; + + case IDC_PROTO: + switch (((LPNMHDR)lParam)->code) { + case TVN_DELETEITEMA: + { + NMTREEVIEWA * pnmtv = (NMTREEVIEWA *) lParam; + if (pnmtv && pnmtv->itemOld.lParam) + mir_free((ProtocolData*)pnmtv->itemOld.lParam); + } + break; + + case NM_CLICK: + { + TVHITTESTINFO hti; + hti.pt.x=(short)LOWORD(GetMessagePos()); + hti.pt.y=(short)HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR)lParam)->hwndFrom,&hti.pt); + if ( TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom, &hti )) { + if ( hti.flags & TVHT_ONITEMICON ) { + TVITEMA tvi; + tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom,&tvi); + + ProtocolData *pData = ( ProtocolData* )tvi.lParam; + if ( pData->enabled ) { + tvi.iImage = tvi.iSelectedImage = !tvi.iImage; + pData->show = tvi.iImage; + TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom,&tvi); + SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0); + } } } } } + break; + } + break; + } + return FALSE; +} diff --git a/StopSpamPlus/src/options.cpp b/StopSpamPlus/src/options.cpp new file mode 100644 index 0000000..52fab03 --- /dev/null +++ b/StopSpamPlus/src/options.cpp @@ -0,0 +1,133 @@ +#include "../headers.h" + +char * pluginDescription = "No more spam! Robots can't go! Only human beings invited!\r\n\r\n" +"This plugin works pretty simple:\r\n" +"While messages from users on your contact list go as there is no any anti-spam software, " +"messages from unknown users are not delivered to you. " +"But also they are not ignored, this plugin replies with a simple question, " +"and if user gives the right answer plugin adds him to your contact list " +"so that he can contact you."; +TCHAR const * infTalkProtPrefix = _T("StopSpam automatic message:\r\n"); +char const * answeredSetting = "Answered"; +char const * questCountSetting = "QuestionCount"; + +INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + + switch(msg) + { + case WM_INITDIALOG: + { + SetDlgItemTextA(hwnd, ID_DESCRIPTION, pluginDescription); + TranslateDialogDefault(hwnd); + SetDlgItemInt(hwnd, ID_MAXQUESTCOUNT, plSets->MaxQuestCount.Get(), FALSE); + SendDlgItemMessage(hwnd, ID_INFTALKPROT, BM_SETCHECK, plSets->InfTalkProtection.Get() ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_ADDPERMANENT, BM_SETCHECK, plSets->AddPermanent.Get() ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_HANDLEAUTHREQ, BM_SETCHECK, plSets->HandleAuthReq.Get() ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_NOTCASESENS, BM_SETCHECK, plSets->AnswNotCaseSens.Get() ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_REMOVE_TMP_ALL, BM_SETCHECK, plSets->RemTmpAll.Get() ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_HISTORY_LOG, BM_SETCHECK, plSets->HistLog.Get() ? BST_CHECKED : BST_UNCHECKED, 0); + } + return TRUE; + case WM_COMMAND:{ + switch (LOWORD(wParam)) + { + case ID_MAXQUESTCOUNT: + { + if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus()) + return FALSE; + break; + } + } + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case WM_NOTIFY: + { + NMHDR* nmhdr = (NMHDR*)lParam; + switch (nmhdr->code) + { + case PSN_APPLY: + { + plSets->MaxQuestCount=GetDlgItemInt(hwnd, ID_MAXQUESTCOUNT, NULL, FALSE); + plSets->InfTalkProtection=(BST_CHECKED == SendDlgItemMessage(hwnd, ID_INFTALKPROT, BM_GETCHECK, 0, 0)); + plSets->AddPermanent=(BST_CHECKED == SendDlgItemMessage(hwnd, ID_ADDPERMANENT, BM_GETCHECK, 0, 0)); + plSets->HandleAuthReq=(BST_CHECKED == SendDlgItemMessage(hwnd, ID_HANDLEAUTHREQ, BM_GETCHECK, 0, 0)); + plSets->AnswNotCaseSens=(BST_CHECKED == SendDlgItemMessage(hwnd, ID_NOTCASESENS, BM_GETCHECK, 0, 0)); + plSets->RemTmpAll=(BST_CHECKED == SendDlgItemMessage(hwnd, ID_REMOVE_TMP_ALL, BM_GETCHECK, 0, 0)); + plSets->HistLog=(BST_CHECKED == SendDlgItemMessage(hwnd, ID_HISTORY_LOG, BM_GETCHECK, 0, 0)); + } + return TRUE; + } + } + break; + } + return FALSE; +} + +INT_PTR CALLBACK MessagesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + + switch(msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwnd); + SetDlgItemString(hwnd, ID_QUESTION, plSets->Question.Get()); + SetDlgItemString(hwnd, ID_ANSWER, plSets->Answer.Get()); + SetDlgItemString(hwnd, ID_CONGRATULATION, plSets->Congratulation.Get()); + SetDlgItemString(hwnd, ID_AUTHREPL, plSets->AuthRepl.Get()); + SetDlgItemString(hwnd, ID_DIVIDER, plSets->AnswSplitString.Get()); + variables_skin_helpbutton(hwnd, IDC_VARS); + ServiceExists(MS_VARS_FORMATSTRING)?EnableWindow(GetDlgItem(hwnd, IDC_VARS),1):EnableWindow(GetDlgItem(hwnd, IDC_VARS),0); + } + return TRUE; + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case ID_QUESTION: + case ID_ANSWER: + case ID_AUTHREPL: + case ID_CONGRATULATION: + case ID_DIVIDER: + { + if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus()) + return FALSE; + break; + } + case ID_RESTOREDEFAULTS: + SetDlgItemString(hwnd, ID_QUESTION, plSets->Question.GetDefault()); + SetDlgItemString(hwnd, ID_ANSWER, plSets->Answer.GetDefault()); + SetDlgItemString(hwnd, ID_CONGRATULATION, plSets->Congratulation.GetDefault()); + SetDlgItemString(hwnd, ID_AUTHREPL, plSets->AuthRepl.GetDefault()); + SetDlgItemString(hwnd, ID_DIVIDER, plSets->AnswSplitString.GetDefault()); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + return TRUE; + case IDC_VARS: + variables_showhelp(hwnd, msg, VHF_FULLDLG|VHF_SETLASTSUBJECT, NULL, NULL); + return TRUE; + } + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case WM_NOTIFY: + { + NMHDR* nmhdr = (NMHDR*)lParam; + switch (nmhdr->code) + { + case PSN_APPLY: + { + plSets->Question=GetDlgItemString(hwnd, ID_QUESTION); + plSets->Answer=GetDlgItemString(hwnd, ID_ANSWER); + plSets->AuthRepl=GetDlgItemString(hwnd, ID_AUTHREPL); + plSets->Congratulation=GetDlgItemString(hwnd, ID_CONGRATULATION); + plSets->AnswSplitString=GetDlgItemString(hwnd, ID_DIVIDER); + } + return TRUE; + } + } + break; + } + return FALSE; +} diff --git a/StopSpamPlus/src/services.cpp b/StopSpamPlus/src/services.cpp new file mode 100644 index 0000000..fbfb82e --- /dev/null +++ b/StopSpamPlus/src/services.cpp @@ -0,0 +1,82 @@ +#include "../headers.h" + +INT_PTR IsContactPassed(WPARAM wParam, LPARAM /*lParam*/) +{ + HANDLE hContact = ( HANDLE )wParam; + std::string proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + + if ( !plSets->ProtoDisabled( proto.c_str())) + return CS_PASSED; + + if ( DBGetContactSettingByte( hContact, pluginName, answeredSetting, 0 )) + return CS_PASSED; + + if ( !DBGetContactSettingByte( hContact, "CList", "NotOnList", 0) && DBGetContactSettingWord( hContact, proto.c_str(), "SrvGroupId", -1 ) != 1 ) + return CS_PASSED; + + if ( IsExistMyMessage( hContact )) + return CS_PASSED; + + return CS_NOTPASSED; +} + +INT_PTR RemoveTempContacts(WPARAM wParam,LPARAM lParam) +{ + HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + while ( hContact ) { + HANDLE hNext = (HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM )hContact, 0 ); + + DBVARIANT dbv = { 0 }; + if ( DBGetContactSettingTString( hContact, "CList", "Group", &dbv )) + dbv.ptszVal = NULL; + + if ( DBGetContactSettingByte( hContact, "CList", "NotOnList", 0 ) || lstrcmp(dbv.ptszVal, _T("Not In List")) == 0 || DBGetContactSettingByte(hContact, "CList", "Hidden", 0 )) { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if ( szProto != NULL ) { + // Check if protocol uses server side lists + DWORD caps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0); + if ( caps & PF1_SERVERCLIST ) { + int status; + status = CallProtoService(szProto, PS_GETSTATUS, 0, 0); + if (status == ID_STATUS_OFFLINE || (status >= ID_STATUS_CONNECTING && status < ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES)) + // Set a flag so we remember to delete the contact when the protocol goes online the next time + DBWriteContactSettingByte( hContact, "CList", "Delete", 1 ); + else + CallService( MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0 ); + } + } + } + + DBFreeVariant( &dbv ); + hContact = hNext; + } + + int hGroup = 1; + char *group_name; + do { + group_name = (char *)CallService(MS_CLIST_GROUPGETNAME, (WPARAM)hGroup, 0); + if ( group_name && lstrcmpA(group_name, "Not In List") == 0 ) { + BYTE ConfirmDelete = DBGetContactSettingByte(NULL, "CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT); + if ( ConfirmDelete ) + DBWriteContactSettingByte( NULL, "CList", "ConfirmDelete", 0 ); + + CallService( MS_CLIST_GROUPDELETE, (WPARAM)hGroup, 0 ); + if ( ConfirmDelete ) + DBWriteContactSettingByte( NULL, "CList", "ConfirmDelete", ConfirmDelete ); + break; + } + hGroup++; + } + while( group_name ); + if (!lParam) + MessageBox(NULL, TranslateT("Complete"), TranslateT(pluginName), MB_ICONINFORMATION); + + return 0; +} + +int OnSystemModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + if (plSets->RemTmpAll.Get()) + RemoveTempContacts(0,1); + return 0; +} diff --git a/StopSpamPlus/src/settings.cpp b/StopSpamPlus/src/settings.cpp new file mode 100644 index 0000000..39ce0c9 --- /dev/null +++ b/StopSpamPlus/src/settings.cpp @@ -0,0 +1,59 @@ +#include "../headers.h" + +//reading from database------------- +tstring db_usage::DBGetPluginSetting(std::string const &name, tstring const &defValue) +{ + DBVARIANT dbv; + if(DBGetContactSettingTString(NULL, pluginName, name.c_str(), &dbv)) + return defValue; + tstring value = dbv.ptszVal; + DBFreeVariant(&dbv); + return value; +} + +#ifdef _UNICODE +std::string db_usage::DBGetPluginSetting(std::string const &name, std::string const &defValue) +{ + DBVARIANT dbv; + if(DBGetContactSettingString(NULL, pluginName, name.c_str(), &dbv)) + return defValue; + std::string value = dbv.pszVal; + DBFreeVariant(&dbv); + return value; +} +#endif + +bool db_usage::DBGetPluginSetting(std::string const &name, bool const &defValue) +{ + return(0 != DBGetContactSettingByte(NULL, pluginName, name.c_str(), defValue?1:0)); +} + +DWORD db_usage::DBGetPluginSetting(std::string const &name, DWORD const &defValue) +{ + return DBGetContactSettingDword(NULL, pluginName, name.c_str(), defValue); +} + +//writting to database-------------- +void db_usage::DBSetPluginSetting(std::string const &name, tstring const &value) +{ + DBWriteContactSettingTString(NULL, pluginName, name.c_str(), value.c_str()); +} + +#ifdef _UNICODE +void db_usage::DBSetPluginSetting(std::string const &name, std::string const &value) +{ + DBWriteContactSettingString(NULL, pluginName, name.c_str(), value.c_str()); +} +#endif + +void db_usage::DBSetPluginSetting(std::string const &name, bool const &value) +{ + DBWriteContactSettingByte(NULL, pluginName, name.c_str(), value?1:0); +} + +void db_usage::DBSetPluginSetting(std::string const &name, DWORD const &value) +{ + DBWriteContactSettingDword(NULL, pluginName, name.c_str(),value); +} + +Settings *plSets; diff --git a/StopSpamPlus/src/settings.h b/StopSpamPlus/src/settings.h new file mode 100644 index 0000000..5fe2b43 --- /dev/null +++ b/StopSpamPlus/src/settings.h @@ -0,0 +1,100 @@ +#pragma once + +#include "../headers.h" + +class db_usage +{ +public: + //reading from database + static tstring DBGetPluginSetting(std::string const &name, tstring const &defValue); +#ifdef _UNICODE + static std::string DBGetPluginSetting(std::string const &name, std::string const &defValue); +#endif + static bool DBGetPluginSetting(std::string const &name, bool const &defValue); + static DWORD DBGetPluginSetting(std::string const &name, DWORD const &defValue); + //writting to database + static void DBSetPluginSetting(std::string const &name, tstring const &value); +#ifdef _UNICODE + static void DBSetPluginSetting(std::string const &name, std::string const &value); +#endif + static void DBSetPluginSetting(std::string const &name, bool const &value); + static void DBSetPluginSetting(std::string const &name, DWORD const &value); + +}; + +template +class db_setting +{ + std::string m_name; + T m_defValue; + T m_value; +public: + db_setting(std::string const &name, T const &defValue):m_name(name),m_defValue(defValue) + { + m_value=db_usage::DBGetPluginSetting(m_name, m_defValue); + } + const T & GetDefault()const{return m_defValue;} + void Set(T const &value) + { + m_value=value; + db_usage::DBSetPluginSetting(m_name, m_value); + } + const T & Get()const{return m_value;} + db_setting& operator=(T const &value) + { + m_value=value; + db_usage::DBSetPluginSetting(m_name, m_value); + return *this; + } + operator T(){return m_value;} + void SetResident(BOOL bResident){ + CallService(MS_DB_SETSETTINGRESIDENT, bResident, (LPARAM)(pluginName m_name.c_str())); + } +}; + +class Settings +{ +public: + db_setting Question; + db_setting AuthRepl; + db_setting Answer; + db_setting Congratulation; + db_setting DisabledProtoList; + db_setting InfTalkProtection; + db_setting AddPermanent; + db_setting MaxQuestCount; + db_setting HandleAuthReq; + db_setting AnswNotCaseSens; + db_setting AnswSplitString; + db_setting RemTmpAll; + db_setting HistLog; + + Settings():Question("Question",TranslateTS(_T("Spammers made me to install small anti-spam system you are now speaking with. ") + _T("Please reply \"nospam\" without quotes and spaces if you want to contact me.\r\n") + _T("Внимание! Антиспам защита. Ответьте \"nospam\" без кавычек и пробелов, если хотите связаться со мной."))) + ,AuthRepl("AuthReply",TranslateTS(_T("StopSpam: send a message and reply to a anti-spam bot question.\r\n") + _T("Антиспам: отправьте сообщение и ответьте на вопрос антиспам системы."))) + ,Answer("Answer",TranslateT("nospam")) + ,Congratulation("Congratulation",TranslateTS(_T("Congratulations! You just passed human/robot test. Now you can write me a message.\r\n") + _T("Поздравляю! Вы прошли антиспам проверку. Теперь вы можете писать мне."))) + ,DisabledProtoList("DisabledProtoList","MetaContacts RSSNews") + ,InfTalkProtection("InfTalkProtection", 1) + ,AddPermanent("AddPermanent", 0) + ,HandleAuthReq("HandleAuthReq", 0) + ,MaxQuestCount("MaxQuestCount", 2) + ,AnswNotCaseSens("AnswNotCaseSens", 1) + ,AnswSplitString("AnswSplitString",_T("|")) + ,RemTmpAll("RemTmpAll", 1) + ,HistLog("HistLog", 0) + { + const std::string& str = DisabledProtoList.Get(); + if ( !str.empty() && *(str.rbegin()) != ' ' ) + DisabledProtoList=DisabledProtoList.Get()+' '; + } + bool ProtoDisabled(std::string proto) + { + return std::string::npos != DisabledProtoList.Get().find(proto + " "); + } +}; + +extern Settings *plSets; diff --git a/StopSpamPlus/src/stopspam.cpp b/StopSpamPlus/src/stopspam.cpp new file mode 100644 index 0000000..b61ea60 --- /dev/null +++ b/StopSpamPlus/src/stopspam.cpp @@ -0,0 +1,107 @@ +#include "../headers.h" + +struct MM_INTERFACE mmi; +UTF8_INTERFACE utfi; +HANDLE hFunc, hTempRemove; +int hLangpack; + +///////////////////////////////////////////////////////////////////////////////////////// +// returns plugin's extended information + +// {553811EE-DEB6-48b8-8902-A8A00C1FD679} +#define MIID_STOPSPAM { 0x553811ee, 0xdeb6, 0x48b8, { 0x89, 0x2, 0xa8, 0xa0, 0xc, 0x1f, 0xd6, 0x79 } } + +PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESC, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + 0, + MIID_STOPSPAM +}; + +PLUGINLINK *pluginLink; +HINSTANCE hInst; + +_inline unsigned int MakeVer(int a,int b,int c,int d) +{ + return PLUGIN_MAKE_VERSION(a,b,c,d); +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + if ( mirandaVersion < MakeVer(__PRODVERSION_STRING)) + return NULL; + + return &pluginInfoEx; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst = hinstDLL; + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////////////////////// +// returns plugin's interfaces information + +static const MUUID interfaces[] = { MIID_STOPSPAM, MIID_LAST }; + +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + CLISTMENUITEM mi; + pluginLink = link; + mir_getLP(&pluginInfoEx); + mir_getMMI(&mmi); + mir_getUTFI(&utfi); + + plSets=new Settings; + + hFunc = CreateServiceFunction(MS_STOPSPAM_CONTACTPASSED, IsContactPassed); + + HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded); + + // Add deliting temporary contacts + hTempRemove = CreateServiceFunction(MS_STOPSPAM_REMTEMPCONTACTS, RemoveTempContacts); + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.position = -0x7FFFFFFF; + mi.flags = CMIF_TCHAR; + mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + mi.ptszName = _T("Remove Temporary Contacts"); + mi.pszService = pluginName"/RemoveTempContacts"; + CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi); + + miranda::EventHooker::HookAll(); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + miranda::EventHooker::UnhookAll(); + + if(hFunc) + { + DestroyServiceFunction(hFunc); + hFunc = 0; + } + if(hTempRemove) + { + DestroyServiceFunction(hTempRemove); + hFunc = 0; + } + delete plSets; + + return 0; +} \ No newline at end of file diff --git a/StopSpamPlus/src/utils.cpp b/StopSpamPlus/src/utils.cpp new file mode 100644 index 0000000..673a858 --- /dev/null +++ b/StopSpamPlus/src/utils.cpp @@ -0,0 +1,77 @@ +#include "../headers.h" + + +tstring &GetDlgItemString(HWND hwnd, int id) +{ + HWND h = GetDlgItem(hwnd, id); + int len = GetWindowTextLength(h); + TCHAR * buf = new TCHAR[len + 1]; + GetWindowText(h, buf, len + 1); + static tstring s; + s = buf; + delete []buf; + return s; +} + +bool IsExistMyMessage(HANDLE hContact) +{ + DBEVENTINFO dbei = { 0 }; + HANDLE hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0); + while(hDbEvent){ + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + + if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei)) break; + if(dbei.flags & DBEF_SENT){ + // mark contact as Answered + DBWriteContactSettingByte(hContact, pluginName, answeredSetting, 1); + // ...let the event go its way + return true; + } + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0); + } + return false; +} + +void SetDlgItemString(HWND hwndDlg, UINT idItem, std::string const &str) +{ + SetDlgItemTextA(hwndDlg, idItem, str.c_str()); +} + +void SetDlgItemString(HWND hwndDlg, UINT idItem, std::wstring const &str) +{ + SetDlgItemTextW(hwndDlg, idItem, str.c_str()); +} + +tstring variables_parse(tstring const &tstrFormat, HANDLE hContact){ + if (ServiceExists(MS_VARS_FORMATSTRING)) { + FORMATINFO fi; + TCHAR *tszParsed; + tstring tstrResult; + + ZeroMemory(&fi, sizeof(fi)); + fi.cbSize = sizeof(fi); + fi.tszFormat = _tcsdup(tstrFormat.c_str()); + fi.hContact = hContact; + fi.flags |= FIF_TCHAR; + tszParsed = (TCHAR *)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0); + free(fi.tszFormat); + if (tszParsed) { + tstrResult = tszParsed; + CallService(MS_VARS_FREEMEMORY, (WPARAM)tszParsed, 0); + return tstrResult; + } + } + return tstrFormat; +} + +tstring trim(const tstring &tstr, const tstring& trimChars) +{ + size_t s = tstr.find_first_not_of(trimChars); + size_t e = tstr.find_last_not_of (trimChars); + + if ((tstring::npos == s) || ( tstring::npos == e)) + return _T(""); + else + return tstr.substr(s, e - s + 1); +} \ No newline at end of file -- cgit v1.2.3