diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 |
commit | 48540940b6c28bb4378abfeb500ec45a625b37b6 (patch) | |
tree | 2ef294c0763e802f91d868bdef4229b6868527de /plugins/StopSpamPlus/src | |
parent | 5c350913f011e119127baeb32a6aedeb4f0d33bc (diff) |
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/StopSpamPlus/src')
-rw-r--r-- | plugins/StopSpamPlus/src/eventhooker.cpp | 68 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/eventhooker.h | 60 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/events.cpp | 254 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/opt_proto.cpp | 137 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/options.cpp | 133 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/services.cpp | 82 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/settings.cpp | 59 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/settings.h | 100 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/stopspam.cpp | 107 | ||||
-rw-r--r-- | plugins/StopSpamPlus/src/utils.cpp | 77 |
10 files changed, 1077 insertions, 0 deletions
diff --git a/plugins/StopSpamPlus/src/eventhooker.cpp b/plugins/StopSpamPlus/src/eventhooker.cpp new file mode 100644 index 0000000000..f29e5b7da1 --- /dev/null +++ b/plugins/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 <list>
+#include "eventhooker.h"
+
+namespace miranda
+{
+ namespace
+ {
+ std::list<EventHooker*> 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<EventHooker*>::iterator it = eventHookerList.begin(); it != eventHookerList.end(); ++it)
+ {
+ (*it)->Hook();
+ }
+ }
+
+ void EventHooker::UnhookAll()
+ {
+ for(std::list<EventHooker*>::iterator it = eventHookerList.begin(); it != eventHookerList.end(); ++it)
+ {
+ (*it)->Unhook();
+ }
+ }
+}
diff --git a/plugins/StopSpamPlus/src/eventhooker.h b/plugins/StopSpamPlus/src/eventhooker.h new file mode 100644 index 0000000000..b1ca2abede --- /dev/null +++ b/plugins/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 <windows.h>
+#include <string>
+#include <newpluginapi.h>
+
+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/plugins/StopSpamPlus/src/events.cpp b/plugins/StopSpamPlus/src/events.cpp new file mode 100644 index 0000000000..74d41958a6 --- /dev/null +++ b/plugins/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/plugins/StopSpamPlus/src/opt_proto.cpp b/plugins/StopSpamPlus/src/opt_proto.cpp new file mode 100644 index 0000000000..201fba693d --- /dev/null +++ b/plugins/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/plugins/StopSpamPlus/src/options.cpp b/plugins/StopSpamPlus/src/options.cpp new file mode 100644 index 0000000000..52fab03e8f --- /dev/null +++ b/plugins/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/plugins/StopSpamPlus/src/services.cpp b/plugins/StopSpamPlus/src/services.cpp new file mode 100644 index 0000000000..57aaf808df --- /dev/null +++ b/plugins/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")) || !lstrcmp(dbv.ptszVal, TranslateT("Not In List")) || 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/plugins/StopSpamPlus/src/settings.cpp b/plugins/StopSpamPlus/src/settings.cpp new file mode 100644 index 0000000000..39ce0c96df --- /dev/null +++ b/plugins/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/plugins/StopSpamPlus/src/settings.h b/plugins/StopSpamPlus/src/settings.h new file mode 100644 index 0000000000..5fe2b43a39 --- /dev/null +++ b/plugins/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 <typename T>
+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<T>& 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<tstring> Question;
+ db_setting<tstring> AuthRepl;
+ db_setting<tstring> Answer;
+ db_setting<tstring> Congratulation;
+ db_setting<std::string> DisabledProtoList;
+ db_setting<bool> InfTalkProtection;
+ db_setting<bool> AddPermanent;
+ db_setting<DWORD> MaxQuestCount;
+ db_setting<bool> HandleAuthReq;
+ db_setting<bool> AnswNotCaseSens;
+ db_setting<tstring> AnswSplitString;
+ db_setting<bool> RemTmpAll;
+ db_setting<bool> 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/plugins/StopSpamPlus/src/stopspam.cpp b/plugins/StopSpamPlus/src/stopspam.cpp new file mode 100644 index 0000000000..b61ea6039b --- /dev/null +++ b/plugins/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/plugins/StopSpamPlus/src/utils.cpp b/plugins/StopSpamPlus/src/utils.cpp new file mode 100644 index 0000000000..673a858ad2 --- /dev/null +++ b/plugins/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 |