summaryrefslogtreecommitdiff
path: root/plugins/SmartAutoReplier/RulesStorage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/SmartAutoReplier/RulesStorage.cpp')
-rw-r--r--plugins/SmartAutoReplier/RulesStorage.cpp536
1 files changed, 536 insertions, 0 deletions
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 <volodymyr@shcherbyna.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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