diff options
Diffstat (limited to 'plugins/StopSpamMod/src')
| -rwxr-xr-x | plugins/StopSpamMod/src/eventhooker.cpp | 68 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/eventhooker.h | 52 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/globals.h | 20 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/headers.h | 46 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/include/utf8.h | 34 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/include/utf8/checked.h | 327 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/include/utf8/core.h | 329 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/include/utf8/unchecked.h | 228 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/init.cpp | 251 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/options.cpp | 475 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/options.h | 1 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/resource.h | 68 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/stopspam.cpp | 390 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/stopspam.h | 31 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/utilities.cpp | 551 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/utilities.h | 19 | ||||
| -rwxr-xr-x | plugins/StopSpamMod/src/version.h | 6 | 
17 files changed, 2896 insertions, 0 deletions
diff --git a/plugins/StopSpamMod/src/eventhooker.cpp b/plugins/StopSpamMod/src/eventhooker.cpp new file mode 100755 index 0000000000..5518577bac --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/eventhooker.h b/plugins/StopSpamMod/src/eventhooker.h new file mode 100755 index 0000000000..31640ffafa --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/globals.h b/plugins/StopSpamMod/src/globals.h new file mode 100755 index 0000000000..790458e6bc --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/headers.h b/plugins/StopSpamMod/src/headers.h new file mode 100755 index 0000000000..18993e70ef --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/include/utf8.h b/plugins/StopSpamMod/src/include/utf8.h new file mode 100755 index 0000000000..4e4451403f --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/include/utf8/checked.h b/plugins/StopSpamMod/src/include/utf8/checked.h new file mode 100755 index 0000000000..3b00644444 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/include/utf8/core.h b/plugins/StopSpamMod/src/include/utf8/core.h new file mode 100755 index 0000000000..693d388c07 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/include/utf8/unchecked.h b/plugins/StopSpamMod/src/include/utf8/unchecked.h new file mode 100755 index 0000000000..b4547fad94 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/init.cpp b/plugins/StopSpamMod/src/init.cpp new file mode 100755 index 0000000000..8bccf59052 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/options.cpp b/plugins/StopSpamMod/src/options.cpp new file mode 100755 index 0000000000..76e448e84b --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/options.h b/plugins/StopSpamMod/src/options.h new file mode 100755 index 0000000000..e32791e98b --- /dev/null +++ b/plugins/StopSpamMod/src/options.h @@ -0,0 +1 @@ +extern HINSTANCE hInst;
\ No newline at end of file diff --git a/plugins/StopSpamMod/src/resource.h b/plugins/StopSpamMod/src/resource.h new file mode 100755 index 0000000000..05f1ba3267 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/stopspam.cpp b/plugins/StopSpamMod/src/stopspam.cpp new file mode 100755 index 0000000000..5c13ec6056 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/stopspam.h b/plugins/StopSpamMod/src/stopspam.h new file mode 100755 index 0000000000..94300b9713 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/utilities.cpp b/plugins/StopSpamMod/src/utilities.cpp new file mode 100755 index 0000000000..3685091b25 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/utilities.h b/plugins/StopSpamMod/src/utilities.h new file mode 100755 index 0000000000..62a3ef5750 --- /dev/null +++ b/plugins/StopSpamMod/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/StopSpamMod/src/version.h b/plugins/StopSpamMod/src/version.h new file mode 100755 index 0000000000..1641ff5c9c --- /dev/null +++ b/plugins/StopSpamMod/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  | 
