diff options
author | Alexander Gluzsky <sss123next@list.ru> | 2012-07-29 22:28:01 +0000 |
---|---|---|
committer | Alexander Gluzsky <sss123next@list.ru> | 2012-07-29 22:28:01 +0000 |
commit | 665dff741463a16792e8ac84833d9043c5b12a09 (patch) | |
tree | 676134001fed45d89383539abda60ff5d237e1e1 /plugins/stopspam_mod | |
parent | cd5ff5d9f38af6280e03a6e18df761461c395dcd (diff) |
added stopspam_mod port
git-svn-id: http://svn.miranda-ng.org/main/trunk@1264 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/stopspam_mod')
22 files changed, 3478 insertions, 0 deletions
diff --git a/plugins/stopspam_mod/Makefile b/plugins/stopspam_mod/Makefile new file mode 100755 index 0000000000..4df12dca59 --- /dev/null +++ b/plugins/stopspam_mod/Makefile @@ -0,0 +1,24 @@ +CFLAGS=-Os -fomit-frame-pointer -pipe -march=i686 -mdll -mwin32 -mwindows -I../miranda-im/miranda/include -I/home/sss/temp/windows/libs/utf8cpp/include -D UNICODE -D _UNICODE -DBUILD_DLL +CXXFLAGS=${CFLAGS} +LDFLAGS=-shared -Wl,--subsystem,windows,--kill-at +CPPFLAGS = +CC=i686-pc-mingw32-gcc +CXX=i686-pc-mingw32-g++ +STRIP=i686-pc-mingw32-strip +WINDRES=i686-pc-mingw32-windres +LD=i686-pc-mingw32-ld +LNK_COMMON=-lkernel32 -lboost_thread_win32-mt -lboost_system-mt -lboost_random-mt -lboost_regex-mt +MAINOBJS=eventhooker.o init.o options.o utilities.o stopspam.o +RESOURCES=stopspam.rc + +all: main +main: $(MAINOBJS) + $(WINDRES) -i $(RESOURCES) -o stopspam_res.o + $(CXX) $(MAINOBJS) stopspam_res.o $(LNK_COMMON) $(LDFLAGS) -o stopspam.dll + $(STRIP) stopspam.dll +# upx -9 stopspam.dll +clean: + rm *.o + rm stopspam.dll + + diff --git a/plugins/stopspam_mod/README b/plugins/stopspam_mod/README new file mode 100755 index 0000000000..4f317d214d --- /dev/null +++ b/plugins/stopspam_mod/README @@ -0,0 +1,5 @@ +* Build Dependencies + 1. boost (http://www.boost.org/) + 2. c++ compiller (because of miranda have compiled with MSVC, only msvc compiled builds working fine (i have no success with mingw, please report your result :) )) +* Runtime Dependencies + 1. MIranda IM at least 0.8 (custom builds should be compiled fine against 0.6, 0.7 miranda api) diff --git a/plugins/stopspam_mod/res/stopspam.rc b/plugins/stopspam_mod/res/stopspam.rc new file mode 100755 index 0000000000..fd5b505ee7 --- /dev/null +++ b/plugins/stopspam_mod/res/stopspam.rc @@ -0,0 +1,244 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "src/resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Русский (Россия) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MESSAGES DIALOGEX 0, 0, 302, 225
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_POPUP | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Question: (Ctrl-Enter for carriage return)",IDC_STATIC,0,5,156,8
+ EDITTEXT ID_QUESTION,0,17,300,57,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
+ PUSHBUTTON "Restore defaults",ID_RESTOREDEFAULTS,234,208,66,14,NOT WS_TABSTOP
+ LTEXT "Answer:",IDC_STATIC,0,82,270,8
+ EDITTEXT ID_ANSWER,0,94,300,14,ES_AUTOHSCROLL
+ LTEXT "Congratulation:",IDC_STATIC,0,112,270,8
+ EDITTEXT ID_CONGRATULATION,0,123,300,48,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
+ LTEXT "Auth. request reply:",IDC_STATIC,0,174,270,8
+ EDITTEXT ID_AUTHREPL,0,187,300,14,ES_AUTOHSCROLL
+ CONTROL "Vars",IDC_VARS,"MButtonClass",WS_TABSTOP,0,206,16,16
+END
+
+IDD_PROTO DIALOGEX 0, 0, 230, 173
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Available accounts:",IDC_STATIC,6,8,84,8
+ LISTBOX ID_ALLPROTO,6,20,84,138,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON ">>>>",ID_ADDALL,96,26,36,14
+ PUSHBUTTON ">>",ID_ADD,96,44,36,14
+ PUSHBUTTON "<<",ID_REMOVE,96,62,36,14
+ PUSHBUTTON "<<<<",ID_REMOVEALL,96,80,36,14
+ LTEXT "Filtered accounts:",IDC_STATIC,138,8,85,8
+ LISTBOX ID_USEDPROTO,138,20,84,138,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_MAIN DIALOGEX 0, 0, 309, 219
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ EDITTEXT ID_DESCRIPTION,12,7,290,82,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_TABSTOP
+ LTEXT "Do not send more than ",IDC_STATIC,11,89,87,12,SS_CENTERIMAGE
+ EDITTEXT ID_MAXQUESTCOUNT,107,89,30,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT " questions to one contact (0 - for no limit)",IDC_STATIC,144,89,155,12,SS_CENTERIMAGE
+ CONTROL "Enable StopSpam-StopSpam infinite talk protection",ID_INFTALKPROT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,106,290,10
+ CONTROL "Add contact permanently",ID_ADDPERMANENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,118,290,8
+ CONTROL "Enable auth. requests blocking",ID_HANDLEAUTHREQ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,130,290,8
+ CONTROL "Hide unanswered contacts and spammers from contact list",ID_HIDECONTACTS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,140,290,10
+ CONTROL "Ignore spammers (do not write messages to history)",ID_IGNORESPAMMERS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,151,290,10
+ CONTROL "Log spam to file",ID_LOGSPAMTOFILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,162,290,10
+END
+
+IDD_ADVANCED DIALOGEX 0, 0, 309, 219
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Case insensitive answer checking",IDC_CASE_INSENSITIVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,66,279,10
+ CONTROL "Disable question in invisible mode",IDC_INVIS_DISABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,77,287,10
+ CONTROL "Enable integration with DOS plugin",ID_DOS_INTEGRATION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,89,287,8
+ CONTROL "Exclude contacts which we sending something from spam check",ID_EXCLUDE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,33,287,8
+ CONTROL "Remove Excluded contacts after restart",ID_REMOVE_TMP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,44,287,8
+ CONTROL "Add contacts to specified group:",ID_SPECIALGROUP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,16,196,10
+ EDITTEXT ID_SPECIALGROUPNAME,217,15,79,12,ES_AUTOHSCROLL
+ CONTROL "Ignore URL in messages and auth requests",ID_IGNOREURL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,100,287,10
+ CONTROL "Add contact to server list",IDC_ADDTOSRVLST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,146,187,10
+ EDITTEXT IDC_AUTOADDGROUP,210,144,76,14,ES_AUTOHSCROLL
+ GROUPBOX "After congratulation (ICQ only)",IDC_STATIC,15,135,278,51
+ CONTROL "Automatically grant authorization",IDC_AUTOAUTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,158,263,10
+ CONTROL "Request authorization from contacts which pass stopspam test",IDC_REQAUTH,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,170,267,10
+ CONTROL "Remove all tempory contacts after restart",ID_REMOVE_TMP_ALL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,55,287,8
+ CONTROL "Use regex for answers checking",IDC_REGEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,111,287,10
+ CONTROL "Log Spammers to system history",IDC_HISTORY_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,121,218,10
+ CONTROL "Use math expression in question",IDC_MATH_QUESTION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,188,129,10
+ PUSHBUTTON "Details..",IDC_MATH_DETAILS,152,187,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_MESSAGES, DIALOG
+ BEGIN
+ RIGHTMARGIN, 300
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 222
+ END
+
+ IDD_PROTO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 223
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 166
+ END
+
+ IDD_MAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 302
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 212
+ END
+
+ IDD_ADVANCED, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 302
+ VERTGUIDE, 15
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 212
+ HORZGUIDE, 11
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,0,2,0
+ PRODUCTVERSION 0,7,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Licensed under the terms of the GNU General Public License"
+ VALUE "CompanyName", " "
+ VALUE "FileDescription", "StopSpam plugin for Miranda IM"
+ VALUE "FileVersion", "0.0.2.0"
+ VALUE "InternalName", "stopspam"
+ VALUE "LegalCopyright", "Copyright © 2000-2010 Miranda IM Project. This software is released under the terms of the GNU General Public License."
+ VALUE "OriginalFilename", "stopspam.dll"
+ VALUE "ProductName", "StopSpam"
+ VALUE "ProductVersion", "0.7.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // Русский (Россия) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Английский (США) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Английский (США) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/stopspam_mod/src/eventhooker.cpp b/plugins/stopspam_mod/src/eventhooker.cpp new file mode 100755 index 0000000000..5518577bac --- /dev/null +++ b/plugins/stopspam_mod/src/eventhooker.cpp @@ -0,0 +1,68 @@ +/* eventhooker.cpp +* Copyright (C) Miklashevsky Roman, sss, elzor +* +* 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/stopspam_mod/src/eventhooker.h b/plugins/stopspam_mod/src/eventhooker.h new file mode 100755 index 0000000000..31640ffafa --- /dev/null +++ b/plugins/stopspam_mod/src/eventhooker.h @@ -0,0 +1,52 @@ +/* eventhooker.h - Helper for hooking events in Miranda. +* Copyright (C) Miklashevsky Roman, sss, elzor +* +* 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/stopspam_mod/src/globals.h b/plugins/stopspam_mod/src/globals.h new file mode 100755 index 0000000000..790458e6bc --- /dev/null +++ b/plugins/stopspam_mod/src/globals.h @@ -0,0 +1,20 @@ +#define pluginName "StopSpam" //const char* ?
+/*
+TCHAR const * defAnswer = _T("nospam");
+TCHAR const * defCongratulation =
+_T("Congratulations! You just passed human/robot test. Now you can write me a message.");
+char const * defProtoList = "ICQ\r\n";
+TCHAR const * infTalkProtPrefix = _T("StopSpam automatic message:\r\n");
+char const * answeredSetting = "Answered";
+char const * questCountSetting = "QuestionCount";
+TCHAR const * defAufrepl = _T("StopSpam: send a message and reply to a anti-spam bot question.");*/
+
+
+#ifdef _UNICODE
+typedef std::wstring tstring;
+#define PREF_TCHAR2 PREF_UTF
+#else
+typedef std::string tstring;
+#define PREF_TCHAR2 0
+#endif //_UNICODE
+
diff --git a/plugins/stopspam_mod/src/headers.h b/plugins/stopspam_mod/src/headers.h new file mode 100755 index 0000000000..18993e70ef --- /dev/null +++ b/plugins/stopspam_mod/src/headers.h @@ -0,0 +1,46 @@ +#include <windows.h> +#include <stdio.h> +#include <commctrl.h> +#include <malloc.h> +#include <time.h> +#include <string> +#include <sstream> +#include<fstream> + + +#include <newpluginapi.h> +#include <m_database.h> +#include <m_protosvc.h> +#include <m_options.h> +#include <m_utils.h> +#include <m_langpack.h> +#include <m_clistint.h> +#include <m_skin.h> +#include <m_button.h> +#include <m_contacts.h> + +#include <m_variables.h> +#include <m_folders.h> + + +#include "globals.h" +#include "stopspam.h" +#include "options.h" +#include "eventhooker.h" +#include "version.h" +#include "resource.h" +#include "utilities.h" + +//boost +#include <boost/thread.hpp> +#include <boost/regex.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/nondet_random.hpp> +#include <boost/random/variate_generator.hpp> +#include <boost/random/uniform_int.hpp> + +//utf8cpp +#include <utf8.h> + + +//#include <m_dos.h> diff --git a/plugins/stopspam_mod/src/include/utf8.h b/plugins/stopspam_mod/src/include/utf8.h new file mode 100755 index 0000000000..4e4451403f --- /dev/null +++ b/plugins/stopspam_mod/src/include/utf8.h @@ -0,0 +1,34 @@ +// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/plugins/stopspam_mod/src/include/utf8/checked.h b/plugins/stopspam_mod/src/include/utf8/checked.h new file mode 100755 index 0000000000..3b00644444 --- /dev/null +++ b/plugins/stopspam_mod/src/include/utf8/checked.h @@ -0,0 +1,327 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include <stdexcept> + +namespace utf8 +{ + // Base for the exceptions that may be thrown from the library + class exception : public ::std::exception { + }; + + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public exception { + uint32_t cp; + public: + invalid_code_point(uint32_t cp) : cp(cp) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template <typename octet_iterator> + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!utf8::internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast<uint8_t>(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0); + *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + return result; + } + + template <typename octet_iterator, typename output_iterator> + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = utf8::internal::validate_next(start, end); + switch (err_code) { + case internal::UTF8_OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + utf8::append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + utf8::append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (start != end && utf8::internal::is_trail(*start)) + ++start; + break; + } + } + return out; + } + + template <typename octet_iterator, typename output_iterator> + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); + return utf8::replace_invalid(start, end, out, replacement_marker); + } + + template <typename octet_iterator> + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); + switch (err_code) { + case internal::UTF8_OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template <typename octet_iterator> + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return utf8::next(it, end); + } + + template <typename octet_iterator> + uint32_t prior(octet_iterator& it, octet_iterator start) + { + // can't do much if it == start + if (it == start) + throw not_enough_room(); + + octet_iterator end = it; + // Go back until we hit either a lead octet or start + while (utf8::internal::is_trail(*(--it))) + if (it == start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + return utf8::peek_next(it, end); + } + + /// Deprecated in versions that include "prior" + template <typename octet_iterator> + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (utf8::internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return utf8::next(temp, end); + } + + template <typename octet_iterator, typename distance_type> + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + utf8::next(it, end); + } + + template <typename octet_iterator> + typename std::iterator_traits<octet_iterator>::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits<octet_iterator>::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::next(first, last); + return dist; + } + + template <typename u16bit_iterator, typename octet_iterator> + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + if (utf8::internal::is_trail_surrogate(trail_surrogate)) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast<uint16_t>(trail_surrogate)); + } + else + throw invalid_utf16(static_cast<uint16_t>(cp)); + + } + // Lone trail surrogate + else if (utf8::internal::is_trail_surrogate(cp)) + throw invalid_utf16(static_cast<uint16_t>(cp)); + + result = utf8::append(cp, result); + } + return result; + } + + template <typename u16bit_iterator, typename octet_iterator> + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = utf8::next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast<uint16_t>(cp); + } + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::append(*(start++), result); + + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start != end) + (*result++) = utf8::next(start, end); + + return result; + } + + // The iterator class + template <typename octet_iterator> + class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {}; + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end) : + it(octet_it), range_start(range_start), range_end(range_end) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + utf8::next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + utf8::next(it, range_end); + return temp; + } + iterator& operator -- () + { + utf8::prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/plugins/stopspam_mod/src/include/utf8/core.h b/plugins/stopspam_mod/src/include/utf8/core.h new file mode 100755 index 0000000000..693d388c07 --- /dev/null +++ b/plugins/stopspam_mod/src/include/utf8/core.h @@ -0,0 +1,329 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include <iterator> + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template<typename octet_type> + inline uint8_t mask8(octet_type oc) + { + return static_cast<uint8_t>(0xff & oc); + } + template<typename u16_type> + inline uint16_t mask16(u16_type oc) + { + return static_cast<uint16_t>(0xffff & oc); + } + template<typename octet_type> + inline bool is_trail(octet_type oc) + { + return ((utf8::internal::mask8(oc) >> 6) == 0x2); + } + + template <typename u16> + inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } + + template <typename u16> + inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template <typename u16> + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template <typename u32> + inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); + } + + template <typename octet_iterator> + inline typename std::iterator_traits<octet_iterator>::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = utf8::internal::mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + template <typename octet_difference_type> + inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) + { + if (cp < 0x80) { + if (length != 1) + return true; + } + else if (cp < 0x800) { + if (length != 2) + return true; + } + else if (cp < 0x10000) { + if (length != 3) + return true; + } + + return false; + } + + enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + /// Helper for get_sequence_x + template <typename octet_iterator> + utf_error increase_safely(octet_iterator& it, octet_iterator end) + { + if (++it == end) + return NOT_ENOUGH_ROOM; + + if (!utf8::internal::is_trail(*it)) + return INCOMPLETE_SEQUENCE; + + return UTF8_OK; + } + + #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} + + /// get_sequence_x functions decode utf-8 sequences of the length x + template <typename octet_iterator> + utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + return UTF8_OK; + } + + template <typename octet_iterator> + utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); + + return UTF8_OK; + } + + template <typename octet_iterator> + utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + template <typename octet_iterator> + utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + + template <typename octet_iterator> + utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type; + const octet_difference_type length = utf8::internal::sequence_length(it); + + // Get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) { + case 0: + return INVALID_LEAD; + case 1: + err = utf8::internal::get_sequence_1(it, end, cp); + break; + case 2: + err = utf8::internal::get_sequence_2(it, end, cp); + break; + case 3: + err = utf8::internal::get_sequence_3(it, end, cp); + break; + case 4: + err = utf8::internal::get_sequence_4(it, end, cp); + break; + } + + if (err == UTF8_OK) { + // Decoding succeeded. Now, security checks... + if (utf8::internal::is_code_point_valid(cp)) { + if (!utf8::internal::is_overlong_sequence(cp, length)){ + // Passed! Return here. + code_point = cp; + ++it; + return UTF8_OK; + } + else + err = OVERLONG_SEQUENCE; + } + else + err = INVALID_CODE_POINT; + } + + // Failure branch - restore the original value of the iterator + it = original_it; + return err; + } + + template <typename octet_iterator> + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + uint32_t ignored; + return utf8::internal::validate_next(it, end, ignored); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template <typename octet_iterator> + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); + if (err_code != internal::UTF8_OK) + return result; + } + return result; + } + + template <typename octet_iterator> + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (utf8::find_invalid(start, end) == end); + } + + template <typename octet_iterator> + inline bool starts_with_bom (octet_iterator it, octet_iterator end) + { + return ( + ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && + ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && + ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) + ); + } + + //Deprecated in release 2.3 + template <typename octet_iterator> + inline bool is_bom (octet_iterator it) + { + return ( + (utf8::internal::mask8(*it++)) == bom[0] && + (utf8::internal::mask8(*it++)) == bom[1] && + (utf8::internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/plugins/stopspam_mod/src/include/utf8/unchecked.h b/plugins/stopspam_mod/src/include/utf8/unchecked.h new file mode 100755 index 0000000000..b4547fad94 --- /dev/null +++ b/plugins/stopspam_mod/src/include/utf8/unchecked.h @@ -0,0 +1,228 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" + +namespace utf8 +{ + namespace unchecked + { + template <typename octet_iterator> + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (cp < 0x80) // one octet + *(result++) = static_cast<uint8_t>(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0); + *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + return result; + } + + template <typename octet_iterator> + uint32_t next(octet_iterator& it) + { + uint32_t cp = utf8::internal::mask8(*it); + typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it); + switch (length) { + case 1: + break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (utf8::internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; + } + ++it; + return cp; + } + + template <typename octet_iterator> + uint32_t peek_next(octet_iterator it) + { + return utf8::unchecked::next(it); + } + + template <typename octet_iterator> + uint32_t prior(octet_iterator& it) + { + while (utf8::internal::is_trail(*(--it))) ; + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + + // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) + template <typename octet_iterator> + inline uint32_t previous(octet_iterator& it) + { + return utf8::unchecked::prior(it); + } + + template <typename octet_iterator, typename distance_type> + void advance (octet_iterator& it, distance_type n) + { + for (distance_type i = 0; i < n; ++i) + utf8::unchecked::next(it); + } + + template <typename octet_iterator> + typename std::iterator_traits<octet_iterator>::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits<octet_iterator>::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::unchecked::next(first); + return dist; + } + + template <typename u16bit_iterator, typename octet_iterator> + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + } + result = utf8::unchecked::append(cp, result); + } + return result; + } + + template <typename u16bit_iterator, typename octet_iterator> + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start < end) { + uint32_t cp = utf8::unchecked::next(start); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast<uint16_t>(cp); + } + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::unchecked::append(*(start++), result); + + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = utf8::unchecked::next(start); + + return result; + } + + // The iterator class + template <typename octet_iterator> + class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { + octet_iterator it; + public: + iterator () {}; + explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + bool operator == (const iterator& rhs) const + { + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + ::std::advance(it, utf8::internal::sequence_length(it)); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + ::std::advance(it, utf8::internal::sequence_length(it)); + return temp; + } + iterator& operator -- () + { + utf8::unchecked::prior(it); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::unchecked::prior(it); + return temp; + } + }; // class iterator + + } // namespace utf8::unchecked +} // namespace utf8 + + +#endif // header guard + diff --git a/plugins/stopspam_mod/src/init.cpp b/plugins/stopspam_mod/src/init.cpp new file mode 100755 index 0000000000..8bccf59052 --- /dev/null +++ b/plugins/stopspam_mod/src/init.cpp @@ -0,0 +1,251 @@ +/* Copyright (C) Miklashevsky Roman, sss, elzor +* +* 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 "headers.h" + + + +BOOL gbDosServiceExist = 0; +BOOL gbVarsServiceExist = 0; + +DWORD gbMaxQuestCount = 5; +BOOL gbInfTalkProtection = 0; +BOOL gbAddPermanent = 0; +BOOL gbHandleAuthReq = 1; +BOOL gbSpecialGroup = 0; +BOOL gbHideContacts = 1; +BOOL gbIgnoreContacts = 0; +BOOL gbExclude = 1; +BOOL gbDelExcluded = 0; +BOOL gbDelAllTempory = 0; +BOOL gbHistoryLog = 0; +BOOL gbDosServiceIntegration = 0; +BOOL gbCaseInsensitive = 0; +BOOL gbRegexMatch = 0; +BOOL gbInvisDisable = 0; +BOOL gbIgnoreURL = 1; +BOOL gbLogToFile=0; +BOOL gbAutoAuth=0; +BOOL gbAutoAddToServerList=0; +BOOL gbAutoReqAuth=1; +BOOL gbMathExpression = 0; + +HANDLE hStopSpamLogDirH=0; + +tstring gbSpammersGroup = _T("Spammers"); +tstring gbAutoAuthGroup = _T("NotSpammers"); + +tstring gbQuestion; +tstring gbAnswer; +tstring gbCongratulation; +std::wstring gbAuthRepl; +extern char * pluginDescription; +extern TCHAR const * defQuestion; +extern int RemoveTmp(WPARAM,LPARAM); + + + +///////////////////////////////////////////////////////////////////////////////////////// +// 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), + 0, + PLUGIN_MAKE_VERSION(0, 0, 2, 0), + pluginDescription, + "Roman Miklashevsky, sss, Elzor", + "sss123next@list.ru", + "© 2004-2012 Roman Miklashevsky, A. Petkevich, Kosh&chka, sss, Elzor", + "http://sss.chaoslab.ru/tracker/mim_plugs/", + UNICODE_AWARE, + MIID_STOPSPAM +}; + + +char *date() +{ + static char d[11]; + char *tmp = __DATE__, m[4], mn[3] = "01"; + m[0]=tmp[0]; + m[1]=tmp[1]; + m[2]=tmp[2]; + if(strstr(m,"Jan")) + strcpy(mn,"01"); + else if(strstr(m,"Feb")) + strcpy(mn,"02"); + else if(strstr(m,"Mar")) + strcpy(mn,"03"); + else if(strstr(m,"Apr")) + strcpy(mn,"04"); + else if(strstr(m,"May")) + strcpy(mn,"05"); + else if(strstr(m,"Jun")) + strcpy(mn,"06"); + else if(strstr(m,"Jul")) + strcpy(mn,"07"); + else if(strstr(m,"Aug")) + strcpy(mn,"08"); + else if(strstr(m,"Sep")) + strcpy(mn,"09"); + else if(strstr(m,"Oct")) + strcpy(mn,"10"); + else if(strstr(m,"Nov")) + strcpy(mn,"11"); + else if(strstr(m,"Dec")) + strcpy(mn,"12"); + d[0]=tmp[7]; + d[1]=tmp[8]; + d[2]=tmp[9]; + d[3]=tmp[10]; + d[4]='.'; + d[5]=mn[0]; + d[6]=mn[1]; + d[7]='.'; + if (tmp[4] == ' ') + d[8] = '0'; + else + d[8]=tmp[4]; + d[9]=tmp[5]; + return d; +} + + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + if ( mirandaVersion < PLUGIN_MAKE_VERSION( 0, 7, 0, 1 )) + return NULL; + { + static char plugname[52]; + strcpy(plugname, pluginName" mod ["); + strcat(plugname, date()); + strcat(plugname, " "); + strcat(plugname, __TIME__); + strcat(plugname, "]"); + pluginInfoEx.shortName = plugname; + } + + return &pluginInfoEx; +} + +extern tstring DBGetContactSettingStringPAN(HANDLE hContact, char const * szModule, char const * szSetting, tstring errorValue); + +void InitVars() +{ + gbDosServiceIntegration = DBGetContactSettingByte(NULL, pluginName, "DOSIntegration", 0); + gbSpammersGroup = DBGetContactSettingStringPAN(NULL, pluginName, "SpammersGroup", _T("Spammers")); + gbAnswer = DBGetContactSettingStringPAN(NULL, pluginName, "answer", _T("nospam")); + gbCongratulation = DBGetContactSettingStringPAN(NULL, pluginName, "congratulation", _T("Congratulations! You just passed human/robot test. Now you can write me a message.")); + gbInfTalkProtection = DBGetContactSettingByte(NULL, pluginName, "infTalkProtection", 0); + gbAddPermanent = DBGetContactSettingByte(NULL, pluginName, "addPermanent", 0); + gbMaxQuestCount = DBGetContactSettingDword(NULL, pluginName, "maxQuestCount", 5); + gbHandleAuthReq = DBGetContactSettingByte(NULL, pluginName, "handleAuthReq", 1); + gbQuestion = DBGetContactSettingStringPAN(NULL, pluginName, "question", defQuestion); + gbAnswer = DBGetContactSettingStringPAN(NULL, pluginName, "answer", _T("nospam")); + gbCongratulation = DBGetContactSettingStringPAN(NULL, pluginName, "congratulation", _T("Congratulations! You just passed human/robot test. Now you can write me a message.")); + gbAuthRepl = DBGetContactSettingStringPAN(NULL, pluginName, "authrepl", _T("StopSpam: send a message and reply to a anti-spam bot question.")); + gbSpecialGroup = DBGetContactSettingByte(NULL, pluginName, "SpecialGroup", 0); + gbHideContacts = DBGetContactSettingByte(NULL, pluginName, "HideContacts", 0); + gbIgnoreContacts = DBGetContactSettingByte(NULL, pluginName, "IgnoreContacts", 0); + gbExclude = DBGetContactSettingByte(NULL, pluginName, "ExcludeContacts", 1); + gbDelExcluded = DBGetContactSettingByte(NULL, pluginName, "DelExcluded", 0); + gbDelAllTempory = DBGetContactSettingByte(NULL, pluginName, "DelAllTempory", 0); + gbCaseInsensitive = DBGetContactSettingByte(NULL, pluginName, "CaseInsensitive", 0); + gbRegexMatch = DBGetContactSettingByte(NULL, pluginName, "RegexMatch", 0); + gbInvisDisable = DBGetContactSettingByte(NULL, pluginName, "DisableInInvis", 0); + gbIgnoreURL = DBGetContactSettingByte(NULL, pluginName, "IgnoreURL", 0); + gbAutoAuthGroup = DBGetContactSettingStringPAN(NULL, pluginName, "AutoAuthGroup", _T("Not Spammers")); + gbAutoAuth=DBGetContactSettingByte(NULL, pluginName, "AutoAuth", 0); + gbAutoAddToServerList=DBGetContactSettingByte(NULL, pluginName, "AutoAddToServerList", 0); + gbAutoReqAuth=DBGetContactSettingByte(NULL, pluginName, "AutoReqAuth", 0); + gbLogToFile=DBGetContactSettingByte(NULL, pluginName, "LogSpamToFile", 0); + gbHistoryLog = DBGetContactSettingByte(NULL, pluginName, "HistoryLog", 0); + gbMathExpression = DBGetContactSettingByte(NULL, pluginName, "MathExpression", 0); + +} + +static int OnSystemModulesLoaded(WPARAM wParam,LPARAM lParam) +{ +/* if (ServiceExists(MS_DOS_SERVICE)) + gbDosServiceExist = TRUE; */ + if (ServiceExists(MS_VARS_FORMATSTRING)) + gbVarsServiceExist = TRUE; + InitVars(); + void CleanThread(); + if(gbDelAllTempory || gbDelExcluded) + boost::thread *thr = new boost::thread(&CleanThread); + // Folders plugin support + if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) + { + hStopSpamLogDirH = (HANDLE) FoldersRegisterCustomPath("StopSpam", "StopSpam Logs", + PROFILE_PATH "\\" CURRENT_PROFILE "\\StopSpamLog"); + } + return 0; +} + +HANDLE hEventFilter = 0, hOptInitialise = 0, hSettingChanged = 0; + + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + /*if(DLL_PROCESS_ATTACH == fdwReason) + hInst=hinstDLL; + return TRUE;*/ + 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; +} + +int hLangpack = 0; + +extern "C" int __declspec(dllexport) Load() +{ + mir_getLP(&pluginInfoEx); + CLISTMENUITEM mi; + CreateServiceFunction("/RemoveTmp", (MIRANDASERVICE)RemoveTmp); + HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded); + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=-0x7FFFFFFF; + mi.flags=0; + mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + mi.pszName="Remove Temporary Contacts"; + mi.pszService="/RemoveTmp"; + + Menu_AddMainMenuItem(&mi); + + miranda::EventHooker::HookAll(); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + miranda::EventHooker::UnhookAll(); + return 0; +} diff --git a/plugins/stopspam_mod/src/options.cpp b/plugins/stopspam_mod/src/options.cpp new file mode 100755 index 0000000000..76e448e84b --- /dev/null +++ b/plugins/stopspam_mod/src/options.cpp @@ -0,0 +1,475 @@ +/* Copyright (C) Miklashevsky Roman, sss, elzor +* +* 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. +*/ + + +#define MIRANDA_VER 0x0800 +#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 * defQuestion = +_T("Spammers made me to install small anti-spam system you are now speaking with.\r\n") +_T("Please reply \"nospam\" without quotes and spaces if you want to contact me."); + + +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, gbMaxQuestCount, FALSE); + SendDlgItemMessage(hwnd, ID_INFTALKPROT, BM_SETCHECK, gbInfTalkProtection ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_ADDPERMANENT, BM_SETCHECK, gbAddPermanent ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_HANDLEAUTHREQ, BM_SETCHECK, gbHandleAuthReq ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_HIDECONTACTS, BM_SETCHECK, gbHideContacts ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_IGNORESPAMMERS, BM_SETCHECK, gbIgnoreContacts ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_LOGSPAMTOFILE, BM_SETCHECK, gbLogToFile ? 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: + { + DBWriteContactSettingDword(NULL, pluginName, "maxQuestCount", gbMaxQuestCount = + GetDlgItemInt(hwnd, ID_MAXQUESTCOUNT, NULL, FALSE)); + DBWriteContactSettingByte(NULL, pluginName, "infTalkProtection", gbInfTalkProtection = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_INFTALKPROT, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "addPermanent", gbAddPermanent = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_ADDPERMANENT, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "handleAuthReq", gbHandleAuthReq = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_HANDLEAUTHREQ, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "HideContacts", gbHideContacts = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_HIDECONTACTS, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "IgnoreContacts", gbIgnoreContacts = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_IGNORESPAMMERS, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "LogSpamToFile", gbLogToFile = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_LOGSPAMTOFILE, 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); + SetDlgItemText(hwnd, ID_QUESTION, gbQuestion.c_str()); + SetDlgItemText(hwnd, ID_ANSWER, gbAnswer.c_str()); + SetDlgItemText(hwnd, ID_CONGRATULATION, gbCongratulation.c_str()); + SetDlgItemText(hwnd, ID_AUTHREPL, gbAuthRepl.c_str()); + EnableWindow(GetDlgItem(hwnd, ID_ANSWER), !gbMathExpression); + variables_skin_helpbutton(hwnd, IDC_VARS); + gbVarsServiceExist?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: + { + if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus()) + return FALSE; + break; + } + case ID_RESTOREDEFAULTS: + SetDlgItemText(hwnd, ID_QUESTION, TranslateTS(defQuestion)); + SetDlgItemText(hwnd, ID_ANSWER, TranslateTS(_T("nospam"))); + SetDlgItemText(hwnd, ID_AUTHREPL, TranslateTS(_T("StopSpam: send a message and reply to a anti-spam bot question."))); + SetDlgItemText(hwnd, ID_CONGRATULATION, TranslateTS(_T("Congratulations! You just passed human/robot test. Now you can write me a message."))); + 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: + { + DBWriteContactSettingTString(NULL, pluginName, "question", + GetDlgItemString(hwnd, ID_QUESTION).c_str()); + gbQuestion = DBGetContactSettingStringPAN(NULL, pluginName, "question", defQuestion); + DBWriteContactSettingTString(NULL, pluginName, "answer", + GetDlgItemString(hwnd, ID_ANSWER).c_str()); + gbAnswer = DBGetContactSettingStringPAN(NULL, pluginName, "answer", _T("nospam")); + DBWriteContactSettingTString(NULL, pluginName, "authrepl", + GetDlgItemString(hwnd, ID_AUTHREPL).c_str()); + gbAuthRepl = DBGetContactSettingStringPAN(NULL, pluginName, "authrepl", _T("StopSpam: send a message and reply to a anti-spam bot question.")); + DBWriteContactSettingTString(NULL, pluginName, "congratulation", + GetDlgItemString(hwnd, ID_CONGRATULATION).c_str()); + gbCongratulation = DBGetContactSettingStringPAN(NULL, pluginName, "congratulation", _T("Congratulations! You just passed human/robot test. Now you can write me a message.")); + } + return TRUE; + } + } + break; + } + return FALSE; +} + +INT_PTR CALLBACK ProtoDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + + switch(msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwnd); + int n; + PROTOCOLDESCRIPTOR** pppd; + if(!CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&n, (WPARAM)&pppd)) + for(int i = 0; i < n; ++i) + { + SendDlgItemMessageA(hwnd, (ProtoInList(pppd[i]->szName) ? ID_USEDPROTO : ID_ALLPROTO), + LB_ADDSTRING, 0, (LPARAM)pppd[i]->szName); + } + } + return TRUE; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case ID_ADD: + { + WPARAM n = (WPARAM)SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_GETCURSEL, 0, 0); + if(LB_ERR != n) + { + size_t len = SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_GETTEXTLEN, n, 0); + if(LB_ERR != len) + { + TCHAR * buf = new TCHAR[len + 1]; + SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_GETTEXT, n, (LPARAM)buf); + SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_ADDSTRING, 0, (LPARAM)buf); + delete []buf; + SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_DELETESTRING, n, 0); + } + } + } + break; + case ID_REMOVE: + { + WPARAM n = (WPARAM)SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_GETCURSEL, 0, 0); + if(LB_ERR != n) + { + size_t len = SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_GETTEXTLEN, n, 0); + if(LB_ERR != len) + { + TCHAR * buf = new TCHAR[len + 1]; + SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_GETTEXT, n, (LPARAM)buf); + SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_ADDSTRING, 0, (LPARAM)buf); + delete []buf; + SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_DELETESTRING, n, 0); + } + } + } + break; + case ID_ADDALL: + for(;;) + { + LRESULT count = SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_GETCOUNT, 0, 0); + if(!count || LB_ERR == count) + break; + SendDlgItemMessage(hwnd, ID_ALLPROTO, LB_SETCURSEL, 0, 0); + SendMessage(hwnd, WM_COMMAND, ID_ADD, 0); + } + break; + case ID_REMOVEALL: + for(;;) + { + LRESULT count = SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_GETCOUNT, 0, 0); + if(!count || LB_ERR == count) + break; + SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_SETCURSEL, 0, 0); + SendMessage(hwnd, WM_COMMAND, ID_REMOVE, 0); + } + break; + default: + return FALSE; + } + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + return TRUE; + case WM_NOTIFY: + { + NMHDR* nmhdr = (NMHDR*)lParam; + switch (nmhdr->code) + { + case PSN_APPLY: + { + LRESULT count = SendDlgItemMessage(hwnd, ID_USEDPROTO, LB_GETCOUNT, 0, 0); + std::ostringstream out; + for(int i = 0; i < count; ++i) + { + size_t len = SendDlgItemMessageA(hwnd, ID_USEDPROTO, LB_GETTEXTLEN, i, 0); + if(LB_ERR != len) + { + char * buf = new char[len + 1]; + SendDlgItemMessageA(hwnd, ID_USEDPROTO, LB_GETTEXT, i, (LPARAM)buf); + out << buf << "\r\n"; + delete []buf; + } + } + DBWriteContactSettingString(NULL, pluginName, "protoList", out.str().c_str()); + } + return TRUE; + } + } + break; + } + return FALSE; +} + +INT_PTR CALLBACK AdvancedDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + + switch(msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwnd); + SendDlgItemMessage(hwnd, IDC_INVIS_DISABLE, BM_SETCHECK, gbInvisDisable ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_CASE_INSENSITIVE, BM_SETCHECK, gbCaseInsensitive ? BST_CHECKED : BST_UNCHECKED, 0); + gbDosServiceExist?EnableWindow(GetDlgItem(hwnd, ID_DOS_INTEGRATION),1):EnableWindow(GetDlgItem(hwnd, ID_DOS_INTEGRATION),0); + SendDlgItemMessage(hwnd, ID_DOS_INTEGRATION, BM_SETCHECK, gbDosServiceIntegration ? BST_CHECKED : BST_UNCHECKED, 0); + SetDlgItemText(hwnd, ID_SPECIALGROUPNAME, gbSpammersGroup.c_str()); + SendDlgItemMessage(hwnd, ID_SPECIALGROUP, BM_SETCHECK, gbSpecialGroup ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_EXCLUDE, BM_SETCHECK, gbExclude ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_REMOVE_TMP, BM_SETCHECK, gbDelExcluded ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_REMOVE_TMP_ALL, BM_SETCHECK, gbDelAllTempory ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, ID_IGNOREURL, BM_SETCHECK, gbIgnoreURL ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_AUTOAUTH, BM_SETCHECK, gbAutoAuth ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_ADDTOSRVLST, BM_SETCHECK, gbAutoAddToServerList ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_REQAUTH, BM_SETCHECK, gbAutoReqAuth ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_REGEX, BM_SETCHECK, gbRegexMatch ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_HISTORY_LOG, BM_SETCHECK, gbHistoryLog ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwnd, IDC_MATH_QUESTION, BM_SETCHECK, gbMathExpression ? BST_CHECKED : BST_UNCHECKED, 0 ); + + SetDlgItemText(hwnd, IDC_AUTOADDGROUP, gbAutoAuthGroup.c_str()); + } + return TRUE; + case WM_COMMAND:{ + switch (LOWORD(wParam)) + { + case IDC_MATH_DETAILS: + { + MessageBox(NULL, TranslateT("If math expression is turned on you can use following expression in message text:\nXX+XX-X/X*X\neach X will be replaced by one ruandom number and answer will be expression result\nMessage must contain only one expression without spaces"), _T("Info"), MB_OK); + } + break; + case IDC_INVIS_DISABLE: + case IDC_CASE_INSENSITIVE: + case ID_DOS_INTEGRATION: + case ID_SPECIALGROUPNAME: + case ID_SPECIALGROUP: + case ID_EXCLUDE: + case ID_REMOVE_TMP: + case ID_REMOVE_TMP_ALL: + case ID_IGNOREURL: + case IDC_AUTOAUTH: + case IDC_ADDTOSRVLST: + case IDC_REQAUTH: + case IDC_AUTOADDGROUP: + case IDC_REGEX: + case IDC_HISTORY_LOG: + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + + } + } + break; + case WM_NOTIFY: + { + NMHDR* nmhdr = (NMHDR*)lParam; + switch (nmhdr->code) + { + case PSN_APPLY: + { + DBWriteContactSettingByte(NULL, pluginName, "CaseInsensitive", gbCaseInsensitive = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_CASE_INSENSITIVE, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "DisableInInvis", gbInvisDisable = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_INVIS_DISABLE, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "DOSIntegration", gbDosServiceIntegration = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_DOS_INTEGRATION, BM_GETCHECK, 0, 0)); + { + static tstring NewGroupName, CurrentGroupName; + NewGroupName = GetDlgItemString(hwnd, ID_SPECIALGROUPNAME); + CurrentGroupName = gbSpammersGroup = DBGetContactSettingStringPAN(NULL, pluginName, "SpammersGroup", _T("0")); + if(wcscmp(CurrentGroupName.c_str(), NewGroupName.c_str()) != 0) + { + int GroupNumber = 0; + BYTE GroupExist = 0; + TCHAR szValue[96] = {0}; + char szNumber[32] = {0}; + extern int CreateCListGroup(TCHAR* szGroupName); + strcpy(szNumber, "0"); + while(strcmp(DBGetContactSettingStringPAN_A(NULL, "CListGroups", szNumber, "0").c_str(), "0") != 0) + { + _itoa(GroupNumber, szNumber, 10); + wcscpy(szValue, DBGetContactSettingStringPAN(NULL, "CListGroups", szNumber, _T("0")).c_str()); + if(wcscmp(NewGroupName.c_str(), szValue + 1) == 0) + { + GroupExist = 1; + break; + } + GroupNumber++; + } + DBWriteContactSettingTString(NULL,pluginName, "SpammersGroup", NewGroupName.c_str()); + gbSpammersGroup = DBGetContactSettingStringPAN(NULL,pluginName,"SpammersGroup", _T("Spammers")); + if(!GroupExist && gbSpecialGroup) + CreateCListGroup((TCHAR*)gbSpammersGroup.c_str()); + } + } + DBWriteContactSettingByte(NULL, pluginName, "SpecialGroup", gbSpecialGroup = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_SPECIALGROUP, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "ExcludeContacts", gbExclude = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_EXCLUDE, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "DelExcluded", gbDelExcluded = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_REMOVE_TMP, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "DelAllTempory", gbDelAllTempory = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_REMOVE_TMP_ALL, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "IgnoreURL", gbIgnoreURL = + BST_CHECKED == SendDlgItemMessage(hwnd, ID_IGNOREURL, BM_GETCHECK, 0, 0)); + + DBWriteContactSettingByte(NULL, pluginName, "AutoAuth", gbAutoAuth = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_AUTOAUTH, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "AutoAddToServerList", gbAutoAddToServerList = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_ADDTOSRVLST, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "AutoReqAuth", gbAutoReqAuth = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_REQAUTH, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "RegexMatch", gbRegexMatch = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_REGEX, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "HistoryLog", gbHistoryLog = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_HISTORY_LOG, BM_GETCHECK, 0, 0)); + DBWriteContactSettingByte(NULL, pluginName, "MathExpression", gbMathExpression = + BST_CHECKED == SendDlgItemMessage(hwnd, IDC_MATH_QUESTION, BM_GETCHECK, 0, 0)); + + { + static tstring NewAGroupName, CurrentAGroupName; + NewAGroupName = GetDlgItemString(hwnd, IDC_AUTOADDGROUP); + CurrentAGroupName = gbAutoAuthGroup = DBGetContactSettingStringPAN(NULL, pluginName, "AutoAuthGroup", _T("0")); + if(wcscmp(CurrentAGroupName.c_str(), NewAGroupName.c_str()) != 0) + { + int GroupNumber = 0; + BYTE GroupExist = 0; + TCHAR szValue[96] = {0}; + char szNumber[32] = {0}; + extern int CreateCListGroup(TCHAR* szGroupName); + strcpy(szNumber, "0"); + while(strcmp(DBGetContactSettingStringPAN_A(NULL, "CListGroups", szNumber, "0").c_str(), "0") != 0) + { + _itoa(GroupNumber, szNumber, 10); + wcscpy(szValue, DBGetContactSettingStringPAN(NULL, "CListGroups", szNumber, _T("0")).c_str()); + if(wcscmp(NewAGroupName.c_str(), szValue + 1) == 0) + { + GroupExist = 1; + break; + } + GroupNumber++; + } + DBWriteContactSettingTString(NULL,pluginName, "AutoAuthGroup", NewAGroupName.c_str()); + gbAutoAuthGroup = DBGetContactSettingStringPAN(NULL,pluginName,"AutoAuthGroup", _T("Not Spammers")); + if(!GroupExist && gbAutoAddToServerList) + CreateCListGroup((TCHAR*)gbAutoAuthGroup.c_str()); + } + } + + } + return TRUE; + } + } + break; + } + return FALSE; +} + + +HINSTANCE hInst; +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; + Options_AddPage(w, &odp); + + + odp.ptszTab = _T("Messages"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_MESSAGES); + odp.pfnDlgProc = MessagesDlgProc; + Options_AddPage(w, &odp); + + odp.ptszTab = _T("Protocols"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROTO); + odp.pfnDlgProc = ProtoDlgProc; + Options_AddPage(w, &odp); + + odp.ptszTab = _T("Advanced"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_ADVANCED); + odp.pfnDlgProc = AdvancedDlgProc; + odp.flags = odp.flags|ODPF_EXPERTONLY; + Options_AddPage(w, &odp); + + return 0; +} + diff --git a/plugins/stopspam_mod/src/options.h b/plugins/stopspam_mod/src/options.h new file mode 100755 index 0000000000..e32791e98b --- /dev/null +++ b/plugins/stopspam_mod/src/options.h @@ -0,0 +1 @@ +extern HINSTANCE hInst;
\ No newline at end of file diff --git a/plugins/stopspam_mod/src/resource.h b/plugins/stopspam_mod/src/resource.h new file mode 100755 index 0000000000..05f1ba3267 --- /dev/null +++ b/plugins/stopspam_mod/src/resource.h @@ -0,0 +1,68 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by stopspam.rc
+//
+#define IDD_MESSAGES 101
+#define IDD_MAIN 103
+#define ID_DESCRIPTION 1001
+#define ID_QUESTION 1002
+#define ID_ANSWER 1003
+#define ID_CONGRATULATION 1004
+#define ID_RESTOREDEFAULTS 1005
+#define ID_ADD 1005
+#define ID_ANSWER2 1007
+#define ID_AUTHREPL 1007
+#define ID_ALLPROTO 1008
+#define IDD_PROTO 1008
+#define ID_MAXQUESTCOUNT 1008
+#define ID_REMOVE 1009
+#define ID_SPECIALGROUPNAME 1009
+#define IDD_ADVANCED 1009
+#define ID_USEDPROTO 1010
+#define ID_REMOVEALL 1011
+#define ID_ADDALL 1012
+#define ID_INFTALKPROT 1013
+#define ID_ADDPERMANENT 1014
+#define ID_ADDPERMANENT2 1015
+#define ID_HANDLEAUTHREQ 1015
+#define ID_DOS_INTEGRATION 1016
+#define ID_SPECIALGROUP 1017
+#define IDC_BUTTON1 1017
+#define IDC_VARS 1017
+#define ID_HIDECONTACTS 1018
+#define IDC_CASE_INSENSITIVE 1018
+#define ID_IGNORESPAMMERS 1019
+#define IDC_CHECK2 1019
+#define IDC_INVIS_DISABLE 1019
+#define ID_REMOVE_TMP 1020
+#define IDC_CUSTOM1 1020
+#define ID_REMOVE_TMP2 1021
+#define ID_EXCLUDE 1021
+#define ID_ADDPERMANENT3 1022
+#define ID_DEL_NO_IN_LIST 1022
+#define IDC_ADDTOSRVLST 1022
+#define ID_IGNOREURL 1023
+#define IDC_EDIT1 1024
+#define IDC_AUTOADDGROUP 1024
+#define IDC_AUTOAUTH 1025
+#define IDC_REQAUTH 1026
+#define IDC_LOGSPAMTOFILE 1027
+#define ID_REMOVE_TMP_ALL 1027
+#define ID_LOGSPAMTOFILE 1027
+#define IDC_REGEX 1028
+#define IDC_CHECK1 1029
+#define IDC_HISTORY_LOG 1029
+#define IDC_MATH_QUESTION 1030
+#define IDC_BUTTON2 1031
+#define IDC_MATH_DETAILS 1031
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1032
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/stopspam_mod/src/stopspam.cpp b/plugins/stopspam_mod/src/stopspam.cpp new file mode 100755 index 0000000000..5c13ec6056 --- /dev/null +++ b/plugins/stopspam_mod/src/stopspam.cpp @@ -0,0 +1,390 @@ +/* Copyright (C) Miklashevsky Roman, sss, elzor +* +* 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 "headers.h" + + +MIRANDA_HOOK_EVENT(ME_DB_CONTACT_ADDED, w, l) +{ + return 0; +} + + +MIRANDA_HOOK_EVENT(ME_DB_EVENT_ADDED, wParam, lParam) +{ + HANDLE hContact = (HANDLE)wParam; + 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(!ProtoInList(dbei.szModule)) { + delete dbei.pBlob; + return 0; + } + + // event is an auth request + if(gbHandleAuthReq) + { + if(!(dbei.flags & DBEF_SENT) && !(dbei.flags & DBEF_READ) && dbei.eventType == EVENTTYPE_AUTHREQUEST) + { + HANDLE hcntct; + hcntct=*((PHANDLE)(dbei.pBlob+sizeof(DWORD))); + + // if request is from unknown or not marked Answered contact + int a = DBGetContactSettingByte(hcntct, "CList", "NotOnList", 0); + int b = !DBGetContactSettingByte(hcntct, pluginName, "Answered", 0); + + if(a && b)// + { + // ...send message + + if(gbHideContacts) + DBWriteContactSettingByte(hcntct, "CList", "Hidden", 1); + if(gbSpecialGroup) + DBWriteContactSettingTString(hcntct, "CList", "Group", gbSpammersGroup.c_str()); + BYTE msg = 1; + if(gbIgnoreURL){ + TCHAR* EventText = ReqGetText(&dbei); //else return NULL + msg=!IsUrlContains(EventText); + mir_free(EventText); + }; + if(gbInvisDisable) + { + if(CallProtoService(dbei.szModule, PS_GETSTATUS, 0, 0) == ID_STATUS_INVISIBLE) + msg = 0; + else if(DBGetContactSettingWord(hContact,dbei.szModule,"ApparentMode",0) == ID_STATUS_OFFLINE) + msg = 0; //is it useful ? + } + if(msg) + { + char * buff=mir_utf8encodeW(variables_parse(gbAuthRepl, hcntct).c_str()); + CallContactService(hcntct, PSS_MESSAGE, PREF_UTF, (LPARAM) buff); + mir_free(buff); + }; + 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(!ProtoInList(dbei->szModule)) + { + // ...let the event go its way + return 0; + } + //do not check excluded contact + + if(DBGetContactSettingByte(hContact, pluginName, "Answered", 0)) + return 0; + if(DBGetContactSettingByte(hContact, pluginName, "Excluded", 0)) + { + if(!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)) + DBDeleteContactSetting(hContact, pluginName, "Excluded"); + return 0; + } + //we want block not only messages, i seen many types other eventtype flood + if(dbei->flags & DBEF_READ) + // ...let the event go its way + return 0; + //mark contact which we trying to contact for exclude from check + if((dbei->flags & DBEF_SENT) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) + && (!gbMaxQuestCount || DBGetContactSettingDword(hContact, pluginName, "QuestionCount", 0) < gbMaxQuestCount) && gbExclude) + { + DBWriteContactSettingByte(hContact, pluginName, "Excluded", 1); + return 0; + } + // if message is from known or marked Answered contact + if(!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)) + // ...let the event go its way + 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_t* msg_u; + char* msg_a = mir_strdup(( char* )dbei->pBlob ); + mir_utf8decode( msg_a, &msg_u ); + message = msg_u; + } + else + message = mir_a2u((char*)(dbei->pBlob)); + + // if message contains right answer... + + BYTE msg = 1; + if(gbInvisDisable) + { + if(CallProtoService(dbei->szModule, PS_GETSTATUS, 0, 0) == ID_STATUS_INVISIBLE) + msg = 0; + else if(DBGetContactSettingWord(hContact,dbei->szModule,"ApparentMode",0) == ID_STATUS_OFFLINE) + msg = 0; //is it useful ? + } + bool answered = false; + if(gbMathExpression) + { + if(boost::algorithm::all(message, boost::is_digit())) + { + int msg = _ttoi(message.c_str()); + int math_answer = DBGetContactSettingDword(hContact, pluginName, "MathAnswer", 0); + if(msg && math_answer) + answered = (msg == math_answer); + } + } + else if(!gbRegexMatch) + answered = gbCaseInsensitive?(!Stricmp(message.c_str(), (variables_parse(gbAnswer, hContact).c_str()))):( !_tcscmp(message.c_str(), (variables_parse(gbAnswer, hContact).c_str()))); + else + { + if(gbCaseInsensitive) + { + std::string check(toUTF8(variables_parse(gbAnswer, hContact))), msg(toUTF8(message)); + boost::algorithm::to_upper(check); + boost::algorithm::to_upper(msg); + boost::regex expr(check); + answered = boost::regex_search(msg.begin(), msg.end(), expr); + } + else + { + std::string check(toUTF8(variables_parse(gbAnswer, hContact))), msg(toUTF8(message)); + boost::regex expr(check); + answered = boost::regex_search(msg.begin(), msg.end(), expr); + } + } + if(answered) + { + // unhide contact + DBDeleteContactSetting(hContact, "CList", "Hidden"); + + DBDeleteContactSetting(hContact, pluginName, "MathAnswer"); + + // mark contact as Answered + DBWriteContactSettingByte(hContact, pluginName, "Answered", 1); + + //add contact permanently + if(gbAddPermanent) //do not use this ) + DBDeleteContactSetting(hContact, "CList", "NotOnList"); + + // send congratulation + if(msg) + { + tstring prot=DBGetContactSettingStringPAN(NULL,dbei->szModule,"AM_BaseProto", _T("")); + // for notICQ protocols or disable auto auth. reqwest + if((Stricmp(_T("ICQ"),prot.c_str()))||(!gbAutoReqAuth)) + { +#ifdef _UNICODE + char * buf=mir_utf8encodeW(variables_parse(gbCongratulation, hContact).c_str()); + CallContactService(hContact, PSS_MESSAGE, PREF_UTF, (LPARAM)buf); + mir_free(buf); +#else + CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)GetCongratulation().c_str()); +#endif + }; + // Note: For ANSI can be not work + if(!Stricmp(_T("ICQ"),prot.c_str())){ + // grand auth. + if(gbAutoAuth) + CallProtoService(dbei->szModule, "/GrantAuth", w, 0); + // add contact to server list and local group + if(gbAutoAddToServerList) + { + DBWriteContactSettingTString(hContact, "CList", "Group", gbAutoAuthGroup.c_str()); + CallProtoService(dbei->szModule, "/AddServerContact", w, 0); + DBDeleteContactSetting(hContact, "CList", "NotOnList"); + }; + // auto auth. reqwest with send congratulation + if(gbAutoReqAuth) + CallContactService(hContact,PSS_AUTHREQUESTW,0, (LPARAM)variables_parse(gbCongratulation, hContact).c_str()); + } + } + return 0; + } + // URL contains check + msg=(msg&&gbIgnoreURL)?(!IsUrlContains((TCHAR *) message.c_str())):msg; + // if message message does not contain infintite talk protection prefix + // and question count for this contact is less then maximum + if(msg) + { + if((!gbInfTalkProtection || tstring::npos==message.find(_T("StopSpam automatic message:\r\n"))) + && (!gbMaxQuestCount || DBGetContactSettingDword(hContact, pluginName, "QuestionCount", 0) < gbMaxQuestCount)) + { + // send question + tstring q; + if(gbInfTalkProtection) + q += _T("StopSpam automatic message:\r\n"); + if(gbMathExpression) + { //parse math expression in question + tstring tmp_question = gbQuestion; + std::list<int> args; + std::list<TCHAR> actions; + tstring::size_type p1 = gbQuestion.find(_T("X")), p2 = 0; + const tstring expr_chars = _T("X+-/*"), expr_acts = _T("+-/*"); + while(p1 < gbQuestion.length() && p1 != tstring::npos && expr_chars.find(gbQuestion[p1]) != tstring::npos) + { + std::string arg; + p2 = p1; +#ifdef UNICODE + for(p1 = gbQuestion.find(_T("X"), p1); (p1 < gbQuestion.length()) && (gbQuestion[p1] == L'X'); ++p1) +#else + for(p1 = gbQuestion.find(_T("X"), p1); gbQuestion[p1] == 'X'; ++p1) +#endif + arg += get_random_num(1); +#ifdef UNICODE + tmp_question.replace(p2, arg.size(), toUTF16(arg)); +#else + tmp_question.replace(p2, arg.size(), arg); +#endif + args.push_back(atoi(arg.c_str())); + if((p1 < gbQuestion.length()) && (p1 != tstring::npos) && (expr_acts.find(gbQuestion[p1]) != tstring::npos)) + actions.push_back(gbQuestion[p1]); + ++p1; + } + int math_answer = 0; + math_answer = args.front(); + args.pop_front(); + while(!args.empty()) + { + if(!actions.empty()) + { + switch(actions.front()) + { + case _T('+'): + { + math_answer += args.front(); + args.pop_front(); + } + break; + case _T('-'): + { + math_answer -= args.front(); + args.pop_front(); + } + break; + case _T('/'): + { + math_answer /= args.front(); + args.pop_front(); + } + break; + case _T('*'): + { + math_answer *= args.front(); + args.pop_front(); + } + break; + } + actions.pop_front(); + } + else + break; + } + DBWriteContactSettingDword(hContact, pluginName, "MathAnswer", math_answer); + q += variables_parse(tmp_question, hContact); + } + else + q += variables_parse(gbQuestion, 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, "QuestionCount", 0); + DBWriteContactSettingDword(hContact, pluginName, "QuestionCount", questCount + 1); + } + else + { +/* if (gbDosServiceExist) + { + if(gbDosServiceIntegration) + { + int i; + i = rand()%255*13; + CallService(MS_DOS_SERVICE, (WPARAM)hContact, (LPARAM)i); + } + } */ + if(gbIgnoreContacts) + { + DBWriteContactSettingDword(hContact, "Ignore", "Mask1", 0x0000007F); + } + } + } + if(gbHideContacts) + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1); + if(gbSpecialGroup) + DBWriteContactSettingTString(hContact, "CList", "Group", gbSpammersGroup.c_str()); + DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + + // save first message from contact + if (DBGetContactSettingDword(hContact, pluginName, "QuestionCount", 0)<2){ + dbei->flags |= DBEF_READ; + CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)dbei); + }; + // reject processing of the event + LogSpamToFile(hContact, message); + return 1; +} + + +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, "Answered"); + DBDeleteContactSetting(hContact, pluginName, "QuestionCount"); + } + + return 0; +} + + + diff --git a/plugins/stopspam_mod/src/stopspam.h b/plugins/stopspam_mod/src/stopspam.h new file mode 100755 index 0000000000..94300b9713 --- /dev/null +++ b/plugins/stopspam_mod/src/stopspam.h @@ -0,0 +1,31 @@ + +extern BOOL gbDosServiceExist; +extern BOOL gbVarsServiceExist; +extern DWORD gbMaxQuestCount; +extern BOOL gbInfTalkProtection; +extern BOOL gbAddPermanent; +extern BOOL gbHandleAuthReq; +extern BOOL gbSpecialGroup; +extern BOOL gbHideContacts; +extern BOOL gbIgnoreContacts; +extern BOOL gbExclude; +extern BOOL gbDelExcluded; +extern BOOL gbDosServiceIntegration; +extern BOOL gbDelNotInList; +extern BOOL gbCaseInsensitive; +extern BOOL gbRegexMatch; +extern BOOL gbHistoryLog; +extern BOOL gbInvisDisable; +extern BOOL gbIgnoreURL; +extern BOOL gbMathExpression; +extern tstring gbSpammersGroup; +extern tstring gbQuestion; +extern tstring gbAnswer; +extern tstring gbCongratulation; +extern std::wstring gbAuthRepl; +extern BOOL gbAutoAuth; +extern BOOL gbAutoAddToServerList; +extern BOOL gbAutoReqAuth; +extern tstring gbAutoAuthGroup; +extern BOOL gbLogToFile; +extern BOOL gbDelAllTempory; diff --git a/plugins/stopspam_mod/src/utilities.cpp b/plugins/stopspam_mod/src/utilities.cpp new file mode 100755 index 0000000000..3685091b25 --- /dev/null +++ b/plugins/stopspam_mod/src/utilities.cpp @@ -0,0 +1,551 @@ +/* Copyright (C) Miklashevsky Roman, sss, elzor +* +* 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 "headers.h" + +tstring DBGetContactSettingStringPAN(HANDLE hContact, char const * szModule, char const * szSetting, tstring errorValue) +{ + DBVARIANT dbv; + //if(DBGetContactSetting(hContact, szModule, szSetting, &dbv)) + if(DBGetContactSettingTString(hContact, szModule, szSetting, &dbv)) + return errorValue; +// if(DBVT_TCHAR == dbv.type ) + errorValue = dbv.ptszVal; + DBFreeVariant(&dbv); + return errorValue; +} + +std::string DBGetContactSettingStringPAN_A(HANDLE hContact, char const * szModule, char const * szSetting, std::string errorValue) +{ + DBVARIANT dbv; + //if(DBGetContactSetting(hContact, szModule, szSetting, &dbv)) + if(DBGetContactSettingString(hContact, szModule, szSetting, &dbv)) + return errorValue; +// if(DBVT_ASCIIZ == dbv.type ) + errorValue = dbv.pszVal; + DBFreeVariant(&dbv); + return errorValue; +} + +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; +} + +std::string &GetProtoList() +{ + static std::string s; + return s = DBGetContactSettingStringPAN_A(NULL, pluginName, "protoList", "ICQ\r\n"); +} + + +bool ProtoInList(std::string proto) +{ + return std::string::npos != GetProtoList().find(proto + "\r\n"); +} + +int CreateCListGroup(TCHAR* szGroupName) +{ + int hGroup; + CLIST_INTERFACE *clint = NULL; + + if (ServiceExists(MS_CLIST_RETRIEVE_INTERFACE)) + clint = (CLIST_INTERFACE*)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, 0); + + hGroup = CallService(MS_CLIST_GROUPCREATE, 0, 0); + + TCHAR* usTmp = szGroupName; + + clint->pfnRenameGroup(hGroup, usTmp); + + return hGroup; +} + +void DeleteCListGroupsByName(TCHAR* szGroupName) +{ + int GroupNumber = 0; + TCHAR szValue[96] = {0}; + char szNumber[32] = {0}; + strcpy(szNumber, "0"); + BYTE ConfirmDelete=DBGetContactSettingByte(NULL, "CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT); + if(ConfirmDelete) + DBWriteContactSettingByte(NULL, "CList", "ConfirmDelete",0); + while(strcmp(DBGetContactSettingStringPAN_A(NULL, "CListGroups", szNumber, "0").c_str(), "0") != 0) + { + wcscpy(szValue, DBGetContactSettingStringPAN(NULL, "CListGroups", szNumber, _T("0")).c_str()); + if(wcscmp(szGroupName, szValue + 1) == 0) + CallService(MS_CLIST_GROUPDELETE,(WPARAM)(HANDLE)GroupNumber+1,0); // bug or ??? @_@ + GroupNumber++; +#if defined(_MSC_VER) && _MSC_VER >= 1300 + _itoa_s(GroupNumber, szNumber, sizeof(szNumber), 10); +#else + _itoa(GroupNumber, szNumber, 10); +#endif + }; + if(ConfirmDelete) + DBWriteContactSettingByte(NULL, "CList", "ConfirmDelete",ConfirmDelete); +} + +/* +void RemoveExcludedUsers() +{ + HANDLE hContact; + hContact_entry *first, *plist, *tmp; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + first = new hContact_entry; + plist = first; + plist->hContact = INVALID_HANDLE_VALUE; + if(hContact) + { + do{ + if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) && DBGetContactSettingByte(hContact, pluginName, "Excluded", 0)) + { + plist->hContact = hContact; + plist->next = new hContact_entry; + plist = plist->next; + plist->hContact = INVALID_HANDLE_VALUE; + } + }while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact, 0)); + + plist = first; + while(plist->hContact != INVALID_HANDLE_VALUE) + { + std::string proto=DBGetContactSettingStringPAN_A(plist->hContact,"Protocol","p",""); + UINT status = CallProtoService(proto.c_str(), PS_GETSTATUS, 0, 0); + + if(status>= ID_STATUS_CONNECTING && status <= ID_STATUS_OFFLINE){ + LogSpamToFile(plist->hContact, _T("Mark for delete")); + DBWriteContactSettingByte(plist->hContact,"CList","Delete", 1); + }else{ + LogSpamToFile(plist->hContact, _T("Deleted")); + CallService(MS_DB_CONTACT_DELETE, (WPARAM)plist->hContact, 0); + }; + tmp = plist; + plist = plist->next; + delete tmp; + } + delete plist; + } +} + +void RemoveTemporaryUsers() +{ + HANDLE hContact; + hContact_entry *first, *plist, *tmp; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + first = new hContact_entry; + plist = first; + plist->hContact = INVALID_HANDLE_VALUE; + if(hContact) + { + do{ + if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)|| + (_T("Not In List")== DBGetContactSettingStringPAN(hContact,"CList","Group",_T(""))) + ) + { + plist->hContact = hContact; + plist->next = new hContact_entry; + plist = plist->next; + plist->hContact = INVALID_HANDLE_VALUE; + } + }while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact, 0)); + + plist = first; + while(plist->hContact != INVALID_HANDLE_VALUE) + { + std::string proto=DBGetContactSettingStringPAN_A(plist->hContact,"Protocol","p",""); + UINT status = CallProtoService(proto.c_str(), PS_GETSTATUS, 0, 0); + + if(status>= ID_STATUS_CONNECTING && status <= ID_STATUS_OFFLINE){ + LogSpamToFile(plist->hContact, _T("Mark for delete")); + DBWriteContactSettingByte(plist->hContact,"CList","Delete", 1); + }else{ + LogSpamToFile(plist->hContact, _T("Deleted")); + CallService(MS_DB_CONTACT_DELETE, (WPARAM)plist->hContact, 0); + }; + + tmp = plist; + plist = plist->next; + delete tmp; + } + delete plist; + }; + DeleteCListGroupsByName(_T("Not In List")); +}*/ +int RemoveTmp(WPARAM,LPARAM) +{ + void CleanThread(); + CleanThread(); + return 0; +} +tstring variables_parse(tstring const &tstrFormat, HANDLE hContact){ + if (gbVarsServiceExist) { + 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; +} + +// case-insensitive _tcscmp +//by nullbie as i remember... +#define NEWTSTR_MALLOC(A) (A==NULL)?NULL:_tcscpy((TCHAR*)mir_alloc(sizeof(TCHAR)*(_tcslen(A)+1)),A) +const int Stricmp(const TCHAR *str, const TCHAR *substr) +{ + int i = 0; + + TCHAR *str_up = NEWTSTR_MALLOC(str); + TCHAR *substr_up = NEWTSTR_MALLOC(substr); + + CharUpperBuff(str_up, lstrlen(str_up)); + CharUpperBuff(substr_up, lstrlen(substr_up)); + + i = _tcscmp(str_up, substr_up); + + mir_free(str_up); + mir_free(substr_up); + + return i; +} + +TCHAR* ReqGetText(DBEVENTINFO* dbei) +{ + if ( !dbei->pBlob ) + return 0; + + char * ptr=(char *)&dbei->pBlob[sizeof(DWORD)*2]; + int len=dbei->cbBlob-sizeof(DWORD)*2; + int i=0; + + while(len&&(i<4)) + { + if(!ptr[0]) i++; + ptr++; + len--; + }; + + if(len) + { + char * tstr=(char *)mir_alloc(len+1); + memcpy(tstr, ptr, len); + tstr[len]=0; + WCHAR* msg = NULL; + msg=(dbei->flags&DBEF_UTF)?mir_utf8decodeW(tstr):mir_a2u(tstr); + mir_free(tstr); + return (TCHAR *)msg; + }; + return 0; +} + + +BOOL IsUrlContains(TCHAR * Str) +{ + const int CountUrl=11; + const TCHAR URL[CountUrl][5]= + { + _T("http"), + _T("www"), + _T(".ru"), + _T(".com"), + _T(".de"), + _T(".cz"), + _T(".org"), + _T(".net"), + _T(".su"), + _T(".ua"), + _T(".tv") + }; + + if(Str&&_tcslen(Str)>0) { + TCHAR *StrLower = NEWTSTR_MALLOC(Str); + CharLowerBuff(StrLower, lstrlen(StrLower)); + for (int i=0; i<CountUrl; i++) + if(_tcsstr (StrLower, URL[i])) + { + mir_free(StrLower); + return 1; + } + mir_free(StrLower); + } + return 0; +} + +tstring GetContactUid(HANDLE hContact, tstring Protocol) +{ + tstring Uid; + TCHAR dUid[32]={0}; + char aUid[32]={0}; + char *szProto = mir_utf8encodeW(Protocol.c_str()); + CONTACTINFO ci; + ZeroMemory((void *)&ci, sizeof(ci)); + + ci.hContact = hContact; + ci.szProto = szProto; + ci.cbSize = sizeof(ci); + + ci.dwFlag = CNF_DISPLAYUID | CNF_TCHAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + switch (ci.type) { + case CNFT_ASCIIZ: + Uid=ci.pszVal; + mir_free((void *)ci.pszVal); + break; + case CNFT_DWORD: +#if defined(_MSC_VER) && _MSC_VER >= 1300 + + _itoa_s(ci.dVal,aUid,32,10); +#else + _itoa(ci.dVal,aUid,10); + +#endif + OemToChar(aUid, dUid); + Uid=dUid; + break; + default: + Uid=_T(""); + break; + }; + } + mir_free(szProto); + return Uid; +} + + +void LogSpamToFile(HANDLE hContact, tstring message) +{ + + if (!gbLogToFile) return; + + tstring LogStrW, LogTime, LogProtocol, LogContactId, LogContactName; + std::string filename; + std::fstream file; + + UINT cbName=255; + char* pszName = (char *)mir_alloc(cbName); + extern HANDLE hStopSpamLogDirH; + + if (FoldersGetCustomPath(hStopSpamLogDirH, pszName, cbName, "")) + CallService(MS_DB_GETPROFILEPATH,(WPARAM) cbName, (LPARAM)pszName); + filename=pszName; + filename=filename+"\\stopspam_mod.log"; + mir_free(pszName); + + file.open(filename.c_str(),std::ios::out |std::ios::app); + + // Time Log line + time_t time_now; + tm *TimeNow; + time(&time_now); + TimeNow = localtime(&time_now); + LogTime=_wasctime( TimeNow ); + // Time Log line + + // Name, UID and Protocol Log line + LogProtocol=DBGetContactSettingStringPAN(hContact,"Protocol","p",_T("")); + LogContactName=(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + LogContactId=(LogProtocol==_T(""))?_T(""):GetContactUid(hContact,LogProtocol); + // Name, UID and Protocol Log line + + LogStrW=_T("[")+LogTime.substr(0,LogTime.length()-1)+_T("] ")+ + LogContactId+_T(" - ")+ + LogContactName+_T(" (")+ + LogProtocol+_T("): ")+ + message+_T("\n"); + + char * buf=mir_u2a(LogStrW.c_str()); + file.write(buf,LogStrW.length()); + mir_free(buf); + + file.close(); + +} + +boost::mutex clean_mutex; + +void CleanProtocolTmpThread(std::string proto) +{ + while(true) + { + UINT status = CallProtoService(proto.c_str(), PS_GETSTATUS, 0, 0); + if(status > ID_STATUS_OFFLINE) + break; + boost::this_thread::sleep(boost::posix_time::seconds(2)); + } + std::list<HANDLE> contacts; + for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + char *proto_tmp = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if(proto_tmp) + if(!strcmp(proto.c_str(), proto_tmp)) + if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)|| (_T("Not In List")== DBGetContactSettingStringPAN(hContact,"CList","Group",_T("")))) + contacts.push_back(hContact); + } + boost::this_thread::sleep(boost::posix_time::seconds(5)); + clean_mutex.lock(); + std::list<HANDLE>::iterator end = contacts.end(); + for(std::list<HANDLE>::iterator i = contacts.begin(); i != end; ++i) + { + LogSpamToFile(*i, _T("Deleted")); + HistoryLogFunc(*i, "Deleted"); + CallService(MS_DB_CONTACT_DELETE, (WPARAM)*i, 0); + } + clean_mutex.unlock(); +} + +void CleanProtocolExclThread(std::string proto) +{ + while(true) + { + UINT status = CallProtoService(proto.c_str(), PS_GETSTATUS, 0, 0); + if(status > ID_STATUS_OFFLINE) + break; + boost::this_thread::sleep(boost::posix_time::seconds(2)); + } + std::list<HANDLE> contacts; + for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + char *proto_tmp = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if(proto_tmp) + if(!strcmp(proto.c_str(), proto_tmp)) + if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) && DBGetContactSettingByte(hContact, pluginName, "Excluded", 0)) + contacts.push_back(hContact); + } + boost::this_thread::sleep(boost::posix_time::seconds(5)); + clean_mutex.lock(); + std::list<HANDLE>::iterator end = contacts.end(); + for(std::list<HANDLE>::iterator i = contacts.begin(); i != end; ++i) + { + LogSpamToFile(*i, _T("Deleted")); + HistoryLogFunc(*i, "Deleted"); + CallService(MS_DB_CONTACT_DELETE, (WPARAM)*i, 0); + } + clean_mutex.unlock(); +} + + +void CleanThread() +{ + std::list<std::string> protocols; + int count = 0; + PROTOACCOUNT **accounts; + ProtoEnumAccounts(&count, &accounts); + for(int i = 0; i < count; i++) + { + if(!strstr(accounts[i]->szModuleName, "MetaContacts") && !strstr(accounts[i]->szModuleName, "Weather")) //not real protocols + protocols.push_back(accounts[i]->szModuleName); + } + std::list<std::string>::iterator end = protocols.end(); + for(std::list<std::string>::iterator i = protocols.begin(); i != end; ++i) + { + if(gbDelAllTempory) + boost::thread *thr = new boost::thread(boost::bind(&CleanProtocolTmpThread, *i)); + if(gbDelExcluded) + boost::thread *thr = new boost::thread(boost::bind(&CleanProtocolExclThread, *i)); + } +} +void HistoryLog(HANDLE hContact, char *data, int event_type, int flags) +{ + DBEVENTINFO Event = {0}; + Event.cbSize = sizeof(Event); + Event.szModule = pluginName; + Event.eventType = event_type; + Event.flags = flags | DBEF_UTF; + Event.timestamp = (DWORD)time(NULL); + Event.cbBlob = strlen(data)+1; + Event.pBlob = (PBYTE)_strdup(data); + CallService(MS_DB_EVENT_ADD, (WPARAM)(HANDLE)hContact,(LPARAM)&Event); +} +void HistoryLogFunc(HANDLE hContact, std::string message) +{ + if(gbHistoryLog) + { + if(hContact == INVALID_HANDLE_VALUE) + return; + std::string msg = message; + msg.append("\n"); + msg.append("Protocol: ").append((char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0)).append(" Contact: "); + msg.append(toUTF8((TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR))).append(" ID: "); + msg.append(toUTF8(GetContactUid(hContact,toUTF16((char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0))))); + HistoryLog(NULL, (char*)msg.c_str(), EVENTTYPE_MESSAGE, DBEF_READ); + } +} + +std::string toUTF8(std::wstring str) +{ + std::string ustr; + try{ + utf8::utf16to8(str.begin(), str.end(), back_inserter(ustr)); + } + catch(const std::exception &e) + { + //TODO: handle utf8cpp exceptions + } + return ustr; +} + +std::string toUTF8(std::string str) +{ + return toUTF8(toUTF16(str)); +} + + +std::wstring toUTF16(std::string str) //convert as much as possible +{ + std::wstring ustr; + std::string tmpstr; + try{ + utf8::replace_invalid(str.begin(), str.end(), back_inserter(tmpstr)); + utf8::utf8to16(tmpstr.begin(), tmpstr.end(), back_inserter(ustr)); + } + catch(const std::exception &e) + { + //TODO: handle utf8cpp exceptions + } + return ustr; +} + +std::string get_random_num(int length) +{ + std::string chars("123456789"); + std::string data; + boost::random_device rng; + boost::variate_generator<boost::random_device&, boost::uniform_int<>> gen(rng, boost::uniform_int<>(0, chars.length()-1)); + for(int i = 0; i < length; ++i) + data += chars[gen()]; + return data; +} diff --git a/plugins/stopspam_mod/src/utilities.h b/plugins/stopspam_mod/src/utilities.h new file mode 100755 index 0000000000..62a3ef5750 --- /dev/null +++ b/plugins/stopspam_mod/src/utilities.h @@ -0,0 +1,19 @@ +tstring DBGetContactSettingStringPAN(HANDLE hContact, char const * szModule, char const * szSetting, tstring errorValue); +std::string DBGetContactSettingStringPAN_A(HANDLE hContact, char const * szModule, char const * szSetting, std::string errorValue); +tstring &GetDlgItemString(HWND hwnd, int id); +std::string &GetProtoList(); +bool ProtoInList(std::string proto); +void RemoveExcludedUsers(); +tstring variables_parse(tstring const &tstrFormat, HANDLE hContact); +const int Stricmp(const TCHAR *str, const TCHAR *substr); +//const int Stristr(const TCHAR *str, const TCHAR *substr); +TCHAR* ReqGetText(DBEVENTINFO* dbei); +BOOL IsUrlContains(TCHAR * Str); +void DeleteCListGroupsByName(TCHAR* szGroupName); +tstring GetContactUid(HANDLE hContact, std::string Protocol); +void LogSpamToFile(HANDLE hContact, tstring message); +std::string toUTF8(std::wstring str); +std::string toUTF8(std::string str); +std::wstring toUTF16(std::string str); +void HistoryLogFunc(HANDLE hContact, std::string message); +std::string get_random_num(int length);
\ No newline at end of file diff --git a/plugins/stopspam_mod/src/version.h b/plugins/stopspam_mod/src/version.h new file mode 100755 index 0000000000..1641ff5c9c --- /dev/null +++ b/plugins/stopspam_mod/src/version.h @@ -0,0 +1,6 @@ +#ifndef VERSION_H_CAA3B062_9BEE_40e6_A9F9_20BBF467731B +#define VERSION_H_CAA3B062_9BEE_40e6_A9F9_20BBF467731B + +#define SUBWCREV (0) + +#endif diff --git a/plugins/stopspam_mod/stopspam_10.vcxproj b/plugins/stopspam_mod/stopspam_10.vcxproj new file mode 100755 index 0000000000..a412f624a1 --- /dev/null +++ b/plugins/stopspam_mod/stopspam_10.vcxproj @@ -0,0 +1,244 @@ +п»ї<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>stopspam</ProjectName>
+ <ProjectGuid>{3E6CEC79-5E93-4607-B10E-498586ECF6A6}</ProjectGuid>
+ <RootNamespace>stopspam</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;STOPSPAM_EXPORTS;%(PreprocessorDefinitions);_UNICODE;UNICODE;_CRT_SECURE_NO_DEPRECATE</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(ProjectName).dll</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>c:\debug\stopspam.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(OutDir)stopspam.lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>X:\temp\windows\libs\Boost\lib;$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>X:\temp\windows\libs\boost;X:\temp\windows\libs\utf8cpp\include;X:\install\git\miranda\miranda-im\miranda\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;STOPSPAM_EXPORTS;%(PreprocessorDefinitions);_UNICODE;UNICODE;_CRT_SECURE_NO_DEPRECATE</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(ProjectName).dll</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)stopspam.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(OutDir)stopspam.lib</ImportLibrary>
+ <AdditionalLibraryDirectories>X:\temp\windows\libs\boost\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>X:\install\git\miranda\miranda_ng_svn\plugins\stopspam_mod\src\include;X:\temp\windows\libs\Boost\include;..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;STOPSPAM_EXPORTS;%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AssemblyDebug>true</AssemblyDebug>
+ <SubSystem>NotSet</SubSystem>
+ <OptimizeReferences>
+ </OptimizeReferences>
+ <EnableCOMDATFolding>
+ </EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>
+ </ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>X:\temp\windows\libs\Boost\lib32;%(AdditionalLibraryDirectories);$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>C:\Program Files\boost\boost_1_34_1\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;STOPSPAM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(ProjectName).dll</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AssemblyDebug>true</AssemblyDebug>
+ <SubSystem>NotSet</SubSystem>
+ <OptimizeReferences>
+ </OptimizeReferences>
+ <EnableCOMDATFolding>
+ </EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>
+ </ImportLibrary>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="src\eventhooker.h" />
+ <ClInclude Include="src\globals.h" />
+ <ClInclude Include="src\headers.h" />
+ <ClInclude Include="src\options.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\stopspam.h" />
+ <ClInclude Include="src\utilities.h" />
+ <ClInclude Include="src\version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\eventhooker.cpp" />
+ <ClCompile Include="src\init.cpp" />
+ <ClCompile Include="src\options.cpp" />
+ <ClCompile Include="src\stopspam.cpp" />
+ <ClCompile Include="src\utilities.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\stopspam.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/plugins/stopspam_mod/stopspam_10.vcxproj.filters b/plugins/stopspam_mod/stopspam_10.vcxproj.filters new file mode 100755 index 0000000000..ae17f570aa --- /dev/null +++ b/plugins/stopspam_mod/stopspam_10.vcxproj.filters @@ -0,0 +1,65 @@ +п»ї<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\eventhooker.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\globals.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\headers.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\options.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\stopspam.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\utilities.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\eventhooker.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\init.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\stopspam.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\utilities.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\stopspam.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file |