From 345930435561acd026c9356f01065e7ee0e92101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Tue, 29 Oct 2013 22:15:21 +0000 Subject: Adopted SmartAutoReplier plugin First compilable version. git-svn-id: http://svn.miranda-ng.org/main/trunk@6693 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SmartAutoReplier/RulesStorage.cpp | 536 ++++++++++++++++++++++++++++++ 1 file changed, 536 insertions(+) create mode 100644 plugins/SmartAutoReplier/RulesStorage.cpp (limited to 'plugins/SmartAutoReplier/RulesStorage.cpp') diff --git a/plugins/SmartAutoReplier/RulesStorage.cpp b/plugins/SmartAutoReplier/RulesStorage.cpp new file mode 100644 index 0000000000..6b4f6a2ab0 --- /dev/null +++ b/plugins/SmartAutoReplier/RulesStorage.cpp @@ -0,0 +1,536 @@ +/* + * Smart Auto Replier (SAR) - auto replier plugin for Miranda IM + * + * Copyright (C) 2004 - 2012 by Volodymyr M. Shcherbyna + * + * This file is part of SAR. + * + * SAR 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 3 of the License, or + * (at your option) any later version. + * + * SAR 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 SAR. If not, see . +*/ + +#include "stdafx.h" +#include "rulesstorage.h" +#include "crc32static.h" + +extern HINSTANCE hInst; +extern CCrushLog CRUSHLOGOBJ; +extern CMessagesHandler * g_pMessHandler; + +/// ctor... +CRulesStorage::CRulesStorage(void) : m_hFile(NULL) +{ + m_comItem.Message = NULL; +BEGIN_PROTECT_AND_LOG_CODE + MakeFullPath(m_szSettFileName, sizeof(m_szSettFileName), STORAGE_NAME); + InitializeCriticalSection(&m_critSect); +END_PROTECT_AND_LOG_CODE +} + +/// dtor... +CRulesStorage::~CRulesStorage(void) +{ +BEGIN_PROTECT_AND_LOG_CODE + DeleteCriticalSection(&m_critSect); + DeInit(); +END_PROTECT_AND_LOG_CODE +} + +bool CRulesStorage::Serialize(ISettingsStream *pSettings, DWORD & ObjectSize) +{ +BEGIN_PROTECT_AND_LOG_CODE + Flush(); +END_PROTECT_AND_LOG_CODE + return true; +} + +bool CRulesStorage::Deserialize(DWORD & ObjectSize) +{ +BEGIN_PROTECT_AND_LOG_CODE + Init(); +END_PROTECT_AND_LOG_CODE + return false; +} + +/// deiniting... +void CRulesStorage::DeInit(void) +{ +BEGIN_PROTECT_AND_LOG_CODE + if (m_hFile && m_hFile != INVALID_HANDLE_VALUE) + CloseHandle(m_hFile); + + m_hFile = NULL; + + /// now release memory... + for (RulesHash::iterator it = m_hashTable.begin(); it != m_hashTable.end(); it++) + { + RULE_ITEM & i = it->second; + + delete i.ContactName; + delete i.ReplyText; + delete i.RuleName; + } + + m_hashTable.clear(); + + if (m_comItem.Message != NULL) + { + delete m_comItem.Message; + m_comItem.Message = NULL; + } + +END_PROTECT_AND_LOG_CODE +} + +/// writing a string into a file.. +void CRulesStorage::RawWriteDataBufByChunk(LPTSTR str) +{ +BEGIN_PROTECT_AND_LOG_CODE + int nLength = _tcslen(str) * sizeof(TCHAR); + DWORD dwWritten = 0; + BOOL bVal = FALSE; + + bVal = WriteFile(m_hFile, &nLength, sizeof(nLength), &dwWritten, NULL); + + if (!bVal || dwWritten != sizeof(nLength)) + throw bVal; + + bVal = WriteFile(m_hFile, str, nLength, &dwWritten, NULL); + if (!bVal || nLength != dwWritten) + { + throw bVal; + } +END_PROTECT_AND_LOG_CODE +} + +/// flushing all data from memory into a file... +void CRulesStorage::Flush(void) +{ +BEGIN_PROTECT_AND_LOG_CODE + RulesHash::iterator it; + + SetFilePointer(m_hFile, NULL, NULL, FILE_BEGIN); + SetEndOfFile(m_hFile); /// clear old data + + SetCommonMessages(); + + for (it = m_hashTable.begin(); it != m_hashTable.end(); it++) + { + FlushItem(it->second); + } + +END_PROTECT_AND_LOG_CODE +} + +/// n.c. +bool CRulesStorage::IsRuleMatch(RULE_METAINFO & info, LPTSTR & strMess, LPTSTR & lpIncomingMsg) +{ +BEGIN_PROTECT_AND_LOG_CODE + EnterCriticalSection(&m_critSect); + + RulesHash::iterator iter; + bool bExists = false; + DWORD dwCRC32 = 0; + CCrc32Static::StringCrc32(info.ContactName, dwCRC32); + iter = m_hashTable.find(dwCRC32); + + CScriptsReader & screader = g_pMessHandler->getSettings().getScriptsReader(); + + if (iter != m_hashTable.end()) + { + /// I have to make copy of ReplyText, + /// cause GetReturnedMessage will release ptr + /// that is stored rule + /// found this bug after 20 min. of debugging ;( + strMess = new TCHAR[_tcslen(iter->second.ReplyText) + (1 * sizeof(TCHAR))]; + + if (strMess == NULL) /// ooops... + { + //screader.GetReturnMessage(info.ContactName, strMess, lpIncomingMsg); + LeaveCriticalSection(&m_critSect); + + return false; + } + + memset(strMess, 0, _tcslen(iter->second.ReplyText) * sizeof(TCHAR) + (1 * sizeof(TCHAR))); + _tcscpy(strMess, iter->second.ReplyText); + bExists = true; + //screader.GetReturnMessage(iter->second.ContactName, strMess, lpIncomingMsg); + } + else + screader.GetReturnMessage(info.ContactName, strMess, lpIncomingMsg); + + LeaveCriticalSection(&m_critSect); + return bExists; +END_PROTECT_AND_LOG_CODE + return false; +} + +/// adding rule into memory... +DWORD CRulesStorage::AddRuleItem(RULE_ITEM item, bool & bExists) +{ +BEGIN_PROTECT_AND_LOG_CODE + DWORD dwCRC32 = NULL; + CCrc32Static::StringCrc32(item.ContactName, dwCRC32); + RulesHash::iterator iter; + iter = m_hashTable.find(dwCRC32); + + if (iter != m_hashTable.end()) + { + bExists = true; + return 0; + } + + bExists = false; + + m_hashTable.insert(RulesHash::value_type(dwCRC32, item)); + return dwCRC32; +END_PROTECT_AND_LOG_CODE + return 0; +} + +/// flushing item... +void CRulesStorage::FlushItem(RULE_ITEM & item) +{ +BEGIN_PROTECT_AND_LOG_CODE + RawWriteDataBufByChunk(item.RuleName); + RawWriteDataBufByChunk(item.ContactName); + RawWriteDataBufByChunk(item.ReplyText); + //RawWriteDataBufByChunk(item.ReplyAction); +END_PROTECT_AND_LOG_CODE +} + +/// initing rules manager... +void CRulesStorage::Init(void) +{ +#ifdef _DEBUG + //MessageBox (NULL, __FUNCTION__, __FILE__, MB_OK); +#endif +BEGIN_PROTECT_AND_LOG_CODE + if (m_hFile) + CloseHandle (m_hFile); + + bool bFileExists = true; + if (!PathFileExists(m_szSettFileName)) + {/// file does not exists... + /// need to fill it with common rules... + bFileExists = false; + } + + m_hFile = CreateFile (m_szSettFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, (bFileExists ? OPEN_ALWAYS : CREATE_ALWAYS), FILE_ATTRIBUTE_NORMAL, NULL); + + if (m_hFile == INVALID_HANDLE_VALUE) + {/// show notification msg to user.. + throw INVALID_HANDLE_VALUE; + } + + if (bFileExists == false) + { + ClearCommonMessages(); + m_comItem.Message = new TCHAR[sizeof(SETTINGS_DEF_MESSAGE) / sizeof(TCHAR) + sizeof(TCHAR)]; + + if (m_comItem.Message != NULL) + { + memset(m_comItem.Message, 0, sizeof(SETTINGS_DEF_MESSAGE) / sizeof(TCHAR) + sizeof(TCHAR)); + _tcscpy(m_comItem.Message, SETTINGS_DEF_MESSAGE); + SetCommonMessages(); + } + } + + DWORD dwSize = 0; + dwSize = GetFileSize(m_hFile, &dwSize); + + DWORD dwReaded = 0, + dwCrc32 = 0; + + int nLength = 0; + + /// suppose that func is failed + BOOL bReaded = FALSE; + bool bFailed = false; + + if (bFileExists) + { + dwSize -= GetCommonMessages(); + } + else + { + dwSize -= _tcslen(SETTINGS_DEF_MESSAGE) * sizeof(TCHAR); + dwSize -= 1 * sizeof(int); + } + + while (dwSize) + { + RULE_ITEM it; + + bReaded = ReadFile(m_hFile, &nLength, sizeof(nLength), &dwReaded, NULL); + + if (bReaded == FALSE || dwReaded != sizeof(nLength)) + { + bFailed = true; + break; + } + + dwSize -= sizeof(nLength); + it.RuleName = new TCHAR[nLength / sizeof(TCHAR) + (1 * sizeof(TCHAR))]; + + if (it.RuleName == NULL) + { + bFailed = true; + break; + } + + memset(it.RuleName, 0, (nLength + (1 * sizeof(TCHAR)))); + + bReaded = ReadFile(m_hFile, it.RuleName, nLength, &dwReaded, NULL); + if (bReaded == FALSE || dwReaded != (nLength)) + { + delete it.RuleName; + bFailed = true; + break; + } + + dwSize -= dwReaded; + bReaded = ReadFile(m_hFile, &nLength, sizeof(nLength), &dwReaded, NULL); + + if (bReaded == FALSE || dwReaded != sizeof(nLength)) + { + delete it.RuleName; + bFailed = true; + break; + } + + dwSize -= sizeof(nLength); + it.ContactName = new TCHAR[nLength / sizeof(TCHAR) + (1 * sizeof(TCHAR))]; + + if (it.ContactName == NULL) + { + delete it.RuleName; + bFailed = true; + break; + } + + memset(it.ContactName, 0, (nLength + (1 * sizeof(TCHAR)))); + bReaded = ReadFile(m_hFile, it.ContactName, nLength, &dwReaded, NULL); + + if (bReaded == FALSE || dwReaded != (nLength)) + { + delete it.RuleName; + delete it.ContactName; + bFailed = true; + break; + } + + dwSize -= dwReaded; + bReaded = ReadFile (m_hFile, &nLength, sizeof(nLength), &dwReaded, NULL); + + if (bReaded == FALSE || dwReaded != sizeof(nLength)) + { + delete it.RuleName; + delete it.ContactName; + bFailed = true; + break; + } + + dwSize -= sizeof(nLength); + it.ReplyText = new TCHAR[nLength / sizeof(TCHAR) + (1 * sizeof(TCHAR))]; + + if (it.ReplyText == NULL) + { + delete it.RuleName; + delete it.ContactName; + bFailed = true; + break; + } + + memset(it.ReplyText, 0, (nLength + (1 * sizeof(TCHAR)))); + bReaded = ReadFile (m_hFile, it.ReplyText, nLength, &dwReaded, NULL); + + if (bReaded == FALSE || dwReaded != (nLength)) + { + delete it.RuleName; + delete it.ContactName; + delete it.ReplyText; + + bFailed = true; + break; + } + + dwSize -= dwReaded; + + dwCrc32 = NULL; + CCrc32Static::StringCrc32(it.ContactName, dwCrc32); + m_hashTable.insert(RulesHash::value_type(dwCrc32, it) ); /// filling list + } + + if (bFailed) + { /// upps... + bool bdelete = NotifyAboutWrongSettings(m_szSettFileName); + + if (bdelete) + { + CloseHandle (m_hFile); + m_hFile = NULL; + DeleteFile (m_szSettFileName); + DeInit(); + Init(); + } + } + +END_PROTECT_AND_LOG_CODE +} + +/// reading an data from file storage... +UINT CRulesStorage::RawReadDataBufByChunk(LPTSTR & szData) +{ +BEGIN_PROTECT_AND_LOG_CODE + UINT nRetVal = 0; + + if (m_hFile == NULL || m_hFile == INVALID_HANDLE_VALUE) + { + return nRetVal; + } + + int nSizeOf = 0; + DWORD dwReaded = 0; + const int nsizeof = sizeof(nSizeOf); + BOOL bReaded = ReadFile(m_hFile, &nSizeOf, nsizeof, &dwReaded, NULL); + nRetVal += dwReaded; + + if (bReaded == FALSE || dwReaded != nsizeof) + { + return nRetVal; + } + + szData = new TCHAR[(nSizeOf / sizeof(TCHAR)) + (1 * sizeof(TCHAR))]; + + if (szData == NULL) + { + return nRetVal + dwReaded; + } + + memset(szData, 0, nSizeOf + (1 * sizeof(TCHAR))); + bReaded = ReadFile(m_hFile, szData, nSizeOf, &dwReaded, NULL); + nRetVal += dwReaded; + + if (bReaded == FALSE || dwReaded != nSizeOf) + { + delete szData; + szData = NULL; + return nRetVal; + } + + return nRetVal; +END_PROTECT_AND_LOG_CODE +} + +/// +void CRulesStorage::SetCommonMessages(void) +{ +BEGIN_PROTECT_AND_LOG_CODE + RawWriteDataBufByChunk(m_comItem.Message); +END_PROTECT_AND_LOG_CODE +} + +void CRulesStorage::ClearCommonMessages(void) +{ + if (m_comItem.Message) + { + delete m_comItem.Message; + m_comItem.Message = NULL; + } +} + +/// reads from storage common rules - header and +/// message that is replyed to all users... +UINT CRulesStorage::GetCommonMessages(void) +{ +BEGIN_PROTECT_AND_LOG_CODE + ClearCommonMessages(); + UINT nRetVal = 0; + + nRetVal += RawReadDataBufByChunk(m_comItem.Message); + + return nRetVal; +END_PROTECT_AND_LOG_CODE +#undef RAW_DATACLEAR + return 0; +} + +void CRulesStorage::setCommonRule(COMMON_RULE_ITEM r) /// n.c. +{ +BEGIN_PROTECT_AND_LOG_CODE + memcpy (&m_comItem, &r, sizeof(COMMON_RULE_ITEM)); +END_PROTECT_AND_LOG_CODE +} + +COMMON_RULE_ITEM & CRulesStorage::getCommonRule(void) /// n.c. +{ +BEGIN_PROTECT_AND_LOG_CODE + return m_comItem; +END_PROTECT_AND_LOG_CODE +} + +/// getting hash table +RulesHash & CRulesStorage::getHashTable(void) +{ +BEGIN_PROTECT_AND_LOG_CODE + return m_hashTable; +END_PROTECT_AND_LOG_CODE +} + +/// remove rule by its id +bool CRulesStorage::RemReplyAction(DWORD dwCrc32) +{ + bool bRetVal = false; +BEGIN_PROTECT_AND_LOG_CODE + EnterCriticalSection(&m_critSect); + RulesHash::iterator it; + it = m_hashTable.find(dwCrc32); + if (it != m_hashTable.end()) + { + delete it->second.ContactName; + delete it->second.ReplyText; + delete it->second.RuleName; + + m_hashTable.erase(it); + bRetVal = true; + } + LeaveCriticalSection(&m_critSect); +END_PROTECT_AND_LOG_CODE + return bRetVal; +} + +bool CRulesStorage::RuleIsRegistered(LPTSTR lpContactName) +{ +BEGIN_PROTECT_AND_LOG_CODE + bool bRetVal = false; + if (lpContactName == NULL) + return bRetVal; + DWORD dwCRC32 = NULL; + CCrc32Static::StringCrc32(lpContactName, dwCRC32); + RulesHash::iterator iter; + + EnterCriticalSection(&m_critSect); + iter = m_hashTable.find(dwCRC32); + + if (iter != m_hashTable.end()) + { + bRetVal = true; + } + LeaveCriticalSection(&m_critSect); + + return bRetVal; +END_PROTECT_AND_LOG_CODE + return false; +} \ No newline at end of file -- cgit v1.2.3